From 459add6022c83303b0aff49b3d1faff085481438 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 12 Dec 2022 18:42:56 +0300 Subject: [PATCH 01/31] add tulip hook first commit --- .gitmodules | 3 + CMakeLists.txt | 5 ++ codegen/src/ModifyGen.cpp | 12 +-- codegen/src/Shared.hpp | 21 +++++ loader/CMakeLists.txt | 9 +- loader/include/Geode/loader/Hook.hpp | 107 ++++++++++++---------- loader/include/Geode/loader/Mod.hpp | 34 +++---- loader/include/Geode/modify/Modify.hpp | 52 ++++++++--- loader/include/Geode/modify/Traits.hpp | 4 +- loader/include/Geode/modify/Wrapper.hpp | 4 +- loader/src/loader/Hook.cpp | 115 +++++++++++++----------- loader/src/loader/HookImpl.cpp | 91 +++++++++++++++++++ loader/src/loader/HookImpl.hpp | 47 ++++++++++ loader/src/loader/LoaderImpl.cpp | 34 ++++++- loader/src/loader/LoaderImpl.hpp | 8 ++ loader/src/loader/Mod.cpp | 10 ++- loader/src/loader/Patch.cpp | 6 +- loader/tuliphook | 1 + 18 files changed, 408 insertions(+), 155 deletions(-) create mode 100644 loader/src/loader/HookImpl.cpp create mode 100644 loader/src/loader/HookImpl.hpp create mode 160000 loader/tuliphook diff --git a/.gitmodules b/.gitmodules index 062479c6..4cbe5a7d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "loader/minhook"] path = loader/minhook url = https://github.com/TsudaKageyu/minhook +[submodule "loader/tuliphook"] + path = loader/tuliphook + url = https://github.com/altalk23/TulipHook diff --git a/CMakeLists.txt b/CMakeLists.txt index 4491b65c..d36753ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,10 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) add_library(${PROJECT_NAME} INTERFACE) +if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(GEODE_ALWAYS_BUILD_CODEGEN ON) +endif() + if (NOT DEFINED GEODE_DEBUG AND (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)) set(GEODE_DEBUG ON) endif() @@ -41,6 +45,7 @@ set(GEODE_CODEGEN_BINARY_OUT ${CMAKE_CURRENT_BINARY_DIR}/codegen) ExternalProject_Add(CodegenProject SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/codegen CMAKE_CACHE_ARGS "-DCMAKE_INSTALL_PREFIX:STRING=${GEODE_CODEGEN_BINARY_OUT}" + BUILD_ALWAYS ${GEODE_ALWAYS_BUILD_CODEGEN} ) add_custom_command( diff --git a/codegen/src/ModifyGen.cpp b/codegen/src/ModifyGen.cpp index f3bb38f3..c3ccee75 100644 --- a/codegen/src/ModifyGen.cpp +++ b/codegen/src/ModifyGen.cpp @@ -29,11 +29,13 @@ using namespace geode::modifier; namespace geode::modifier {{ {wrap} - template - struct ModifyDerive : ModifyBase> {{ - using ModifyBase>::ModifyBase; + template + struct ModifyDerive : ModifyBase> {{ + using BaseModify = ModifyBase>; + using ModifyBase>::ModifyBase; using Base = {class_name}; - static void apply() {{ + using Derived = Der; + void apply() override {{ using namespace geode::core::meta; )GEN"; @@ -104,7 +106,7 @@ std::string generateModifyHeader(Root& root, ghc::filesystem::path const& single format_strings::apply_function, fmt::arg("addr_index", f.field_id), fmt::arg("pure_index", bank.getPure(*begin, c.name)), fmt::arg("class_name", c.name), fmt::arg("function_name", function_name), - fmt::arg("function_convention", codegen::getConvention(f)) + fmt::arg("function_convention", codegen::getModifyConvention(f)) ); } } diff --git a/codegen/src/Shared.hpp b/codegen/src/Shared.hpp index 91840add..85cc337f 100644 --- a/codegen/src/Shared.hpp +++ b/codegen/src/Shared.hpp @@ -166,6 +166,27 @@ namespace codegen { else throw codegen::error("Tried to get convention of non-function"); } + inline std::string getModifyConvention(Field& f) { + if (codegen::platform != Platform::Windows) return "tulip::hook::DefaultConvention"; + + if (auto fn = f.get_fn()) { + auto status = getStatus(f); + + if (fn->is_static) { + if (status == BindStatus::Binded) return "tulip::hook::CdeclConvention"; + else return "tulip::hook::OptcallConvention"; + } + else if (fn->is_virtual) { + return "tulip::hook::ThiscallConvention"; + } + else { + if (status == BindStatus::Binded) return "tulip::hook::ThiscallConvention"; + else return "tulip::hook::MembercallConvention"; + } + } + 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; diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index b715a2cd..13100803 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -125,9 +125,9 @@ target_compile_definitions(${PROJECT_NAME} PUBLIC GEODE_EXPORTING) add_subdirectory(md4c) target_link_libraries(${PROJECT_NAME} md4c) -# Lilac (hooking) -add_subdirectory(lilac) -target_link_libraries(${PROJECT_NAME} z lilac_hook geode-sdk) +# Tulip hook (hooking) +add_subdirectory(tuliphook) +target_link_libraries(${PROJECT_NAME} z TulipHook geode-sdk) # Use precompiled headers for faster builds target_precompile_headers(${PROJECT_NAME} PRIVATE @@ -154,9 +154,6 @@ if (APPLE) elseif (WIN32) add_subdirectory(launcher/windows) - add_subdirectory(minhook) - target_link_libraries(${PROJECT_NAME} minhook) - # target_include_directories(${PROJECT_NAME} PRIVATE dobby/include) # target_link_directories(${PROJECT_NAME} PRIVATE dobby) # target_link_libraries(${PROJECT_NAME} dobby) diff --git a/loader/include/Geode/loader/Hook.hpp b/loader/include/Geode/loader/Hook.hpp index a3b2515f..72c078b5 100644 --- a/loader/include/Geode/loader/Hook.hpp +++ b/loader/include/Geode/loader/Hook.hpp @@ -6,6 +6,7 @@ #include "../external/json/json.hpp" #include #include +#include namespace geode { class Mod; @@ -13,84 +14,94 @@ namespace geode { class GEODE_DLL Hook { private: - Mod* m_owner; - std::string m_displayName; - void* m_address; - void* m_detour; - core::HookHandle m_handle; - bool m_enabled; - Result (*m_addFunction)(void*); - - // Only allow friend classes to create - // hooks. Whatever method created the - // hook should take care of populating - // m_owner and m_handle. - Hook() : m_enabled(false) {} - - template class Conv, class Ret, class... Args> - static Hook* create(Ret (*address)(Args...), std::string const& displayName, Mod* owner) { - auto ret = new Hook; - ret->m_address = (void*)address; - ret->m_detour = (void*)Detour; - ret->m_owner = owner; - ret->m_displayName = displayName; - ret->m_addFunction = - (Result(*)(void*)) & core::hook::add; - return ret; - } - - // no copying - Hook(Hook const&) = delete; - Hook operator=(Hook const&) = delete; - - // Used by Mod - Result<> enable(); - Result<> disable(); + class Impl; + std::shared_ptr m_impl; + Hook(std::shared_ptr&& impl); + ~Hook(); friend class Mod; friend class Loader; - static std::vector> internalHooks; - static bool readyToHook; - public: + static Hook* create(Mod* owner, void* address, void* detour, std::string const& displayName, tulip::hook::HandlerMetadata const& handlerMetadata, tulip::hook::HookMetadata const& hookMetadata); + + template + static Hook* create(Mod* owner, void* address, DetourType detour, std::string const& displayName, tulip::hook::HookMetadata const& hookMetadata = tulip::hook::HookMetadata()) { + auto handlerMetadata = tulip::hook::HandlerMetadata{ + .m_convention = std::make_shared(), + .m_abstract = tulip::hook::AbstractFunction::from(detour) + }; + return Hook::create(owner, address, reinterpret_cast(detour), displayName, handlerMetadata, hookMetadata); + } + + Hook(Hook const&) = delete; + Hook operator=(Hook const&) = delete; + /** * Get the address of the function hooked. * @returns Address */ - uintptr_t getAddress() const { - return reinterpret_cast(m_address); - } + uintptr_t getAddress() const; /** * Get the display name of the function hooked. * @returns Display name */ - std::string_view getDisplayName() const { - return m_displayName; - } + std::string_view getDisplayName() const; /** * Get whether the hook is enabled or not. * @returns True if enabled, false if not. */ - bool isEnabled() const { - return m_enabled; - } + bool isEnabled() const; /** * Get the owner of this hook. * @returns Pointer to the owner's Mod handle. */ - Mod* getOwner() const { - return m_owner; - } + Mod* getOwner() const; /** * Get info about the hook as JSON * @note For IPC */ nlohmann::json getRuntimeInfo() const; + + /** + * Get the metadata of the hook. + * @returns Hook metadata + */ + tulip::hook::HookMetadata getHookMetadata() const; + + /** + * Set the metadata of the hook. + * @param metadata Hook metadata + */ + void setHookMetadata(tulip::hook::HookMetadata const& metadata); + + /** + * Get the priority of the hook. + * @returns Priority + */ + int32_t getPriority() const; + + /** + * Set the priority of the hook. + * @param priority Priority + */ + void setPriority(int32_t priority); + + /** + * Get whether the hook should be auto enabled or not. + * @returns Auto enable + */ + bool getAutoEnable() const; + + /** + * Set whether the hook should be auto enabled or not. + * @param autoEnable Auto enable + */ + void setAutoEnable(bool autoEnable); }; class GEODE_DLL Patch { diff --git a/loader/include/Geode/loader/Mod.hpp b/loader/include/Geode/loader/Mod.hpp index c6b84ddf..1287c7ff 100644 --- a/loader/include/Geode/loader/Mod.hpp +++ b/loader/include/Geode/loader/Mod.hpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace geode { template @@ -241,31 +242,20 @@ namespace geode { * @param address The absolute address of * the function to hook, i.e. gd_base + 0xXXXX * @param detour Pointer to your detour function + * @param displayName Name of the hook that will be + * displayed in the hook list + * @param hookMetadata Metadata of the hook * @returns Successful result containing the - * Hook handle, errorful result with info on + * Hook pointer, errorful result with info on * error */ - template class Convention> - Result addHook(void* address) { - return this->addHook("", address); - } - - /** - * Create a hook at an address. Call the original - * function by calling the original function – - * no trampoline needed. Also takes a displayName - * parameter to use for when visualizing the hook. - * @param address The absolute address of - * the function to hook, i.e. gd_base + 0xXXXX - * @param detour Pointer to your detour function - * @returns Successful result containing the - * Hook handle, errorful result with info on - * error - */ - template class Convention> - Result addHook(std::string const& displayName, void* address) { - auto hook = - Hook::create((decltype(Detour))address, displayName, this); + template + Result addHook( + void* address, DetourType detour, + std::string const& displayName = "", + tulip::hook::HookMetadata const& hookMetadata = tulip::hook::HookMetadata() + ) { + auto hook = Hook::create(this, address, detour, displayName, hookMetadata); return this->addHook(hook); } diff --git a/loader/include/Geode/modify/Modify.hpp b/loader/include/Geode/modify/Modify.hpp index d4b1c30c..23275278 100644 --- a/loader/include/Geode/modify/Modify.hpp +++ b/loader/include/Geode/modify/Modify.hpp @@ -2,22 +2,28 @@ #include "../meta/meta.hpp" #include "Addresses.hpp" #include "Field.hpp" +#include "IDManager.hpp" #include "Types.hpp" #include "Wrapper.hpp" #include #include #include -#include "IDManager.hpp" +#include -#define GEODE_APPLY_MODIFY_FOR_FUNCTION( \ - addr_index, pure_index, convention, className, functionName \ -) \ - if constexpr (wrap::functionName::uuid != nullptr && (void*)wrap::functionName::uuid != (void*)wrap::functionName::uuid) { \ - (void)Mod::get() \ - ->addHook::value, convention>( \ - #className "::" #functionName, (void*)addresses::address##addr_index() \ - ); \ +#define GEODE_APPLY_MODIFY_FOR_FUNCTION(addr_index, pure_index, convention, className, functionName) \ + { \ + using DerivedWrap = wrap::functionName; \ + using BaseWrap = wrap::functionName; \ + if constexpr (DerivedWrap::uuid != nullptr && (void*)BaseWrap::uuid != (void*)DerivedWrap::uuid) { \ + auto hook = Hook::create( \ + Mod::get(), \ + reinterpret_cast(addresses::address##addr_index()), \ + DerivedWrap::value, \ + #className "::" #functionName \ + ); \ + BaseModify::m_hooks[FunctionUUID::value] = hook; \ + } \ } namespace geode::modifier { @@ -25,15 +31,35 @@ namespace geode::modifier { template class ModifyDerive; - template + template class ModifyBase { public: + std::map m_hooks; + + template + Result getHook() { + auto uuid = FunctionUUID::value; + if (m_hooks.find(uuid) == m_hooks.end()) { + return Err("Hook not in this modify"); + } + return m_hooks[uuid]; + } + // unordered_map idea ModifyBase() { - Loader::get()->scheduleOnModLoad(getMod(), []() { - Derived::apply(); + Loader::get()->scheduleOnModLoad(getMod(), [this]() { + this->apply(); + ModifyDerived::Derived::onModify(*this); + for (auto& [uuid, hook] : m_hooks) { + auto res = Mod::get()->addHook(hook); + if (!res) { + log::error("Failed to add hook: {}", res.error()); + } + } }); } + + virtual void apply() {} template friend class ModifyDerive; // explicit Modify(Property property) idea @@ -59,5 +85,7 @@ namespace geode { public: modifier::FieldIntermediate m_fields; + + static void onModify(auto& self) {} }; } diff --git a/loader/include/Geode/modify/Traits.hpp b/loader/include/Geode/modify/Traits.hpp index cefa006c..b69ef3cc 100644 --- a/loader/include/Geode/modify/Traits.hpp +++ b/loader/include/Geode/modify/Traits.hpp @@ -58,11 +58,11 @@ namespace geode::modifier { * function pointers. */ template - struct function_uuid { + struct FunctionUUID { private: constexpr static void function() {} public: - constexpr static inline void (*value)() = &function_uuid::function; + constexpr static inline void (*value)() = &FunctionUUID::function; }; } diff --git a/loader/include/Geode/modify/Wrapper.hpp b/loader/include/Geode/modify/Wrapper.hpp index e5daa442..6993a90d 100644 --- a/loader/include/Geode/modify/Wrapper.hpp +++ b/loader/include/Geode/modify/Wrapper.hpp @@ -27,7 +27,7 @@ public: \ constexpr static inline auto value = &wrapperImpl; \ constexpr static inline auto uuid = \ - function_uuid(&Class::identifier)>::value; \ + FunctionUUID(&Class::identifier)>::value; \ }; \ /* Specialization - function Return Class::identifier(Parameters...) is a static function */ \ template \ @@ -43,7 +43,7 @@ public: \ constexpr static inline auto value = &wrapperImpl; \ constexpr static inline auto uuid = \ - function_uuid(&Class::identifier)>::value; \ + FunctionUUID(&Class::identifier)>::value; \ }; namespace geode::modifier { diff --git a/loader/src/loader/Hook.cpp b/loader/src/loader/Hook.cpp index 72188dac..25a009ae 100644 --- a/loader/src/loader/Hook.cpp +++ b/loader/src/loader/Hook.cpp @@ -1,50 +1,65 @@ -#include -#include -#include -#include -#include -#include -// #include -#include "InternalMod.hpp" - -#include - -USE_GEODE_NAMESPACE(); - -Result<> Hook::enable() { - if (!m_enabled) { - auto res = std::invoke(m_addFunction, m_address); - if (res) { - log::debug("Enabling hook at function {}", m_displayName); - m_enabled = true; - m_handle = res.unwrap(); - return Ok(); - } - else { - return Err( - "Unable to create hook at " + std::to_string(reinterpret_cast(m_address)) - ); - } - return Err("Hook already has a handle"); - } - return Ok(); -} - -Result<> Hook::disable() { - if (m_enabled) { - if (!geode::core::hook::remove(m_handle)) return Err("Unable to remove hook"); - - log::debug("Disabling hook at function {}", m_displayName); - m_enabled = false; - } - return Ok(); -} - -nlohmann::json Hook::getRuntimeInfo() const { - auto json = nlohmann::json::object(); - json["address"] = reinterpret_cast(m_address); - json["detour"] = reinterpret_cast(m_detour); - json["name"] = m_displayName; - json["enabled"] = m_enabled; - return json; -} +#include +#include +#include +#include +#include +#include +// #include +#include "InternalMod.hpp" + +#include +#include "HookImpl.hpp" + +USE_GEODE_NAMESPACE(); + +Hook::Hook(std::shared_ptr&& impl) : m_impl(std::move(impl)) {} +Hook::~Hook() {} + +static Hook* Hook::create(Mod* owner, void* address, void* detour, std::string const& displayName, tulip::hook::HandlerMetadata const& handlerMetadata, tulip::hook::HookMetadata const& hookMetadata) { + auto impl = std::make_shared(address, detour, displayName, handlerMetadata, hookMetadata, owner); + return new Hook(std::move(impl)); +} + +uintptr_t Hook::getAddress() const { + return m_impl->getAddress(); +} + +std::string_view Hook::getDisplayName() const { + return m_impl->getDisplayName(); +} + +bool Hook::isEnabled() const { + return m_impl->isEnabled(); +} + +Mod* Hook::getOwner() const { + return m_impl->getOwner(); +} + +nlohmann::json Hook::getRuntimeInfo() const { + return m_impl->getRuntimeInfo(); +} + +tulip::hook::HookMetadata Hook::getHookMetadata() const { + return m_impl->getHookMetadata(); +} + +void Hook::setHookMetadata(tulip::hook::HookMetadata const& metadata) { + m_impl->setHookMetadata(metadata); +} + +int32_t Hook::getPriority() const { + return m_impl->getPriority(); +} + +void Hook::setPriority(int32_t priority) { + m_impl->setPriority(priority); +} + +bool getAutoEnable() const { + return m_impl->getAutoEnable(); +} + +void setAutoEnable(bool autoEnable) { + m_impl->setAutoEnable(autoEnable); +} \ No newline at end of file diff --git a/loader/src/loader/HookImpl.cpp b/loader/src/loader/HookImpl.cpp new file mode 100644 index 00000000..20f259df --- /dev/null +++ b/loader/src/loader/HookImpl.cpp @@ -0,0 +1,91 @@ +#include "HookImpl.hpp" + +Hook::Impl::Impl(void* address, void* detour, std::string const& displayName, tulip::hook::HandlerMetadata const& handlerMetadata, tulip::hook::HookMetadata const& hookMetadata, Mod* owner) : + m_address(address), + m_detour(detour), + m_displayName(displayName), + m_handlerMetadata(handlerMetadata), + m_hookMetadata(hookMetadata), + m_owner(owner) {} +Hook::Impl::~Impl() { + if (m_enabled) this->disable(); +} + +uintptr_t Hook::Impl::getAddress() const { + return reinterpret_cast(m_address); +} +std::string_view Hook::Impl::getDisplayName() const { + return m_displayName; +} +bool Hook::Impl::isEnabled() const { + return m_enabled; +} +Mod* Hook::Impl::getOwner() const { + return m_owner; +} +nlohmann::json Hook::Impl::getRuntimeInfo() const { + auto json = nlohmann::json::object(); + json["address"] = reinterpret_cast(m_address); + json["detour"] = reinterpret_cast(m_detour); + json["name"] = m_displayName; + json["enabled"] = m_enabled; + return json; +} +tulip::hook::HookMetadata Hook::Impl::getHookMetadata() const { + return m_hookMetadata; +} + +Result<> Hook::Impl::enable() { + if (!m_enabled) { + if (!LoaderImpl::get()->hasHandler(m_address)) { + GEODE_UNWRAP(LoaderImpl::get()->createHandler(m_address, m_handlerMetadata)); + } + + GEODE_UNWRAP_INTO(auto handler, LoaderImpl::get()->getHandler(m_address)); + + m_handle = tulip::hook::createHook(handler, m_detour, m_hookMetadata); + log::debug("Enabling hook at function {}", m_displayName); + m_enabled = true; + } + return Ok(); +} + +Result<> Hook::Impl::disable() { + if (m_enabled) { + GEODE_UNWRAP_INTO(auto handler, LoaderImpl::get()->getHandler(m_address)); + + tulip::hook::removeHook(handler, m_handle); + + log::debug("Disabling hook at function {}", m_displayName); + m_enabled = false; + } + return Ok(); +} + +Result<> Hook::Impl::updateMetadata() { + if (m_enabled) { + GEODE_UNWRAP_INTO(auto handler, LoaderImpl::get()->getHandler(m_address)); + + tulip::hook::updateHookMetadata(handler, m_handle, m_hookMetadata); + } + return Ok(); +} +void Hook::Impl::setHookMetadata(tulip::hook::HookMetadata const& metadata) { + m_hookMetadata = metadata; + this->updateMetadata(); +} +int32_t Hook::Impl::getPriority() const { + return m_hookMetadata.priority; +} +void Hook::Impl::setPriority(int32_t priority) { + m_hookMetadata.priority = priority; + this->updateMetadata(); +} + +bool Hook::Impl::getAutoEnable() const { + return m_autoEnable; +} + +void Hook::Impl::setAutoEnable(bool autoEnable) { + m_autoEnable = autoEnable; +} \ No newline at end of file diff --git a/loader/src/loader/HookImpl.hpp b/loader/src/loader/HookImpl.hpp new file mode 100644 index 00000000..fd79bc1a --- /dev/null +++ b/loader/src/loader/HookImpl.hpp @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include +// #include +#include "InternalMod.hpp" + +#include + +USE_GEODE_NAMESPACE(); + +class Hook::Impl { +public: + Impl(void* address, void* detour, std::string const& displayName, tulip::hook::HandlerMetadata const& handlerMetadata, tulip::hook::HookMetadata const& hookMetadata, Mod* owner); + ~Impl(); + + + void* m_address; + void* m_detour; + std::string m_displayName; + tulip::hook::HandlerMetadata m_handlerMetadata; + tulip::hook::HookMetadata m_hookMetadata; + Mod* m_owner; + tulip::hook::HookHandle m_handle; + bool m_enabled = false; + bool m_autoEnable = true; + + + // Used by Mod + Result<> enable(); + Result<> disable(); + Result<> updateMetadata(); + + uintptr_t getAddress() const; + std::string_view getDisplayName() const; + bool isEnabled() const; + Mod* getOwner() const; + nlohmann::json getRuntimeInfo() const; + tulip::hook::HookMetadata getHookMetadata() const; + void setHookMetadata(tulip::hook::HookMetadata const& metadata); + int32_t getPriority() const; + void setPriority(int32_t priority); + bool getAutoEnable() const; + void setAutoEnable(bool autoEnable); +}; \ No newline at end of file diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index e40d69b5..f3f6041e 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -593,4 +593,36 @@ ListenerResult ResourceDownloadFilter::handle( return ListenerResult::Propagate; } -ResourceDownloadFilter::ResourceDownloadFilter() {} \ No newline at end of file +ResourceDownloadFilter::ResourceDownloadFilter() {} + + +Result<> Loader::Impl::createHandler(void* address, tulip::hook::HandlerMetadata const& metadata) { + if (m_internalHooks.count(address)) { + return Error("Handler already exists at address"); + } + + GEODE_UNWRAP_INTO(auto handle, tulip::hook::createHandler(address, metadata)); + m_internalHooks[address] = handle; +} + +bool hasHandler(void* address) { + return m_internalHooks.count(address); +} + +Result Loader::Impl::getHandler(void* address) { + if (!m_internalHooks.count(address)) { + return Error("Handler does not exist at address"); + } + + return Ok(m_internalHooks[address]); +} + +Result<> Loader::Impl::removeHandler(void* address) { + if (!m_internalHooks.count(address)) { + return Error("Handler does not exist at address"); + } + + auto handle = m_internalHooks[address]; + tulip::hook::removeHandler(handle); + m_internalHooks.erase(address); +} diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp index 431538f2..944fe651 100644 --- a/loader/src/loader/LoaderImpl.hpp +++ b/loader/src/loader/LoaderImpl.hpp @@ -18,6 +18,7 @@ #include #include #include +#include struct ResourceDownloadEvent : public Event { const UpdateStatus status; @@ -59,6 +60,13 @@ public: std::vector> m_internalHooks; bool m_readyToHook = false; + std::unordered_set m_handlerHandles; + + Result<> createHandler(void* address, tulip::hook::HandlerMetadata const& metadata); + bool hasHandler(void* address); + Result getHandler(void* address); + Result<> removeHandler(void* address); + void downloadLoaderResources(); bool loadHooks(); diff --git a/loader/src/loader/Mod.cpp b/loader/src/loader/Mod.cpp index 56c129c9..090dca1d 100644 --- a/loader/src/loader/Mod.cpp +++ b/loader/src/loader/Mod.cpp @@ -419,10 +419,12 @@ Result<> Mod::disableHook(Hook* hook) { Result Mod::addHook(Hook* hook) { if (LoaderImpl::get()->isReadyToHook()) { - auto res = this->enableHook(hook); - if (!res) { - delete hook; - return Err("Can't create hook"); + if (hook->getAutoEnable()) { + auto res = this->enableHook(hook); + if (!res) { + delete hook; + return Err("Can't create hook"); + } } } else { diff --git a/loader/src/loader/Patch.cpp b/loader/src/loader/Patch.cpp index e5b971f3..59f6e6d2 100644 --- a/loader/src/loader/Patch.cpp +++ b/loader/src/loader/Patch.cpp @@ -1,14 +1,14 @@ #include -#include +// #include USE_GEODE_NAMESPACE(); bool Patch::apply() { - return lilac::hook::write_memory(m_address, m_patch.data(), m_patch.size()); + return tulip::hook::write_memory(m_address, m_patch.data(), m_patch.size()); } bool Patch::restore() { - return lilac::hook::write_memory(m_address, m_original.data(), m_original.size()); + return tulip::hook::write_memory(m_address, m_original.data(), m_original.size()); } nlohmann::json Patch::getRuntimeInfo() const { diff --git a/loader/tuliphook b/loader/tuliphook new file mode 160000 index 00000000..92b3cca3 --- /dev/null +++ b/loader/tuliphook @@ -0,0 +1 @@ +Subproject commit 92b3cca336285ab9028b3e7f59089e6cd215be27 From 437a996b149616fa1e4b5e15cb4b852d3dba2534 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 12 Dec 2022 19:23:11 +0300 Subject: [PATCH 02/31] fix compilation errors --- loader/include/Geode/loader/Hook.hpp | 3 +++ loader/src/loader/Hook.cpp | 13 ++++++++++--- loader/src/loader/HookImpl.cpp | 22 +++++++++++++++++----- loader/src/loader/LoaderImpl.cpp | 26 +++++++++++++------------- loader/src/loader/LoaderImpl.hpp | 2 +- loader/src/loader/Patch.cpp | 4 ++-- 6 files changed, 46 insertions(+), 24 deletions(-) diff --git a/loader/include/Geode/loader/Hook.hpp b/loader/include/Geode/loader/Hook.hpp index 72c078b5..bc64115e 100644 --- a/loader/include/Geode/loader/Hook.hpp +++ b/loader/include/Geode/loader/Hook.hpp @@ -22,6 +22,9 @@ namespace geode { friend class Mod; friend class Loader; + Result<> enable(); + Result<> disable(); + public: static Hook* create(Mod* owner, void* address, void* detour, std::string const& displayName, tulip::hook::HandlerMetadata const& handlerMetadata, tulip::hook::HookMetadata const& hookMetadata); diff --git a/loader/src/loader/Hook.cpp b/loader/src/loader/Hook.cpp index 25a009ae..e9f3e9fd 100644 --- a/loader/src/loader/Hook.cpp +++ b/loader/src/loader/Hook.cpp @@ -15,7 +15,7 @@ USE_GEODE_NAMESPACE(); Hook::Hook(std::shared_ptr&& impl) : m_impl(std::move(impl)) {} Hook::~Hook() {} -static Hook* Hook::create(Mod* owner, void* address, void* detour, std::string const& displayName, tulip::hook::HandlerMetadata const& handlerMetadata, tulip::hook::HookMetadata const& hookMetadata) { +Hook* Hook::create(Mod* owner, void* address, void* detour, std::string const& displayName, tulip::hook::HandlerMetadata const& handlerMetadata, tulip::hook::HookMetadata const& hookMetadata) { auto impl = std::make_shared(address, detour, displayName, handlerMetadata, hookMetadata, owner); return new Hook(std::move(impl)); } @@ -56,10 +56,17 @@ void Hook::setPriority(int32_t priority) { m_impl->setPriority(priority); } -bool getAutoEnable() const { +bool Hook::getAutoEnable() const { return m_impl->getAutoEnable(); } -void setAutoEnable(bool autoEnable) { +void Hook::setAutoEnable(bool autoEnable) { m_impl->setAutoEnable(autoEnable); +} + +Result<> Hook::enable() { + m_impl->enable(); +} +Result<> Hook::disable() { + m_impl->disable(); } \ No newline at end of file diff --git a/loader/src/loader/HookImpl.cpp b/loader/src/loader/HookImpl.cpp index 20f259df..cbb856f3 100644 --- a/loader/src/loader/HookImpl.cpp +++ b/loader/src/loader/HookImpl.cpp @@ -1,4 +1,5 @@ #include "HookImpl.hpp" +#include "LoaderImpl.hpp" Hook::Impl::Impl(void* address, void* detour, std::string const& displayName, tulip::hook::HandlerMetadata const& handlerMetadata, tulip::hook::HookMetadata const& hookMetadata, Mod* owner) : m_address(address), @@ -8,7 +9,12 @@ Hook::Impl::Impl(void* address, void* detour, std::string const& displayName, tu m_hookMetadata(hookMetadata), m_owner(owner) {} Hook::Impl::~Impl() { - if (m_enabled) this->disable(); + if (m_enabled) { + auto res = this->disable(); + if (!res) { + log::error("Failed to disable hook: {}", res.unwrapErr()); + } + } } uintptr_t Hook::Impl::getAddress() const { @@ -72,14 +78,20 @@ Result<> Hook::Impl::updateMetadata() { } void Hook::Impl::setHookMetadata(tulip::hook::HookMetadata const& metadata) { m_hookMetadata = metadata; - this->updateMetadata(); + auto res = this->updateMetadata(); + if (!res) { + log::error("Failed to update hook metadata: {}", res.unwrapErr()); + } } int32_t Hook::Impl::getPriority() const { - return m_hookMetadata.priority; + return m_hookMetadata.m_priority; } void Hook::Impl::setPriority(int32_t priority) { - m_hookMetadata.priority = priority; - this->updateMetadata(); + m_hookMetadata.m_priority = priority; + auto res = this->updateMetadata(); + if (!res) { + log::error("Failed to update hook priority: {}", res.unwrapErr()); + } } bool Hook::Impl::getAutoEnable() const { diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index f3f6041e..77f900e0 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -597,32 +597,32 @@ ResourceDownloadFilter::ResourceDownloadFilter() {} Result<> Loader::Impl::createHandler(void* address, tulip::hook::HandlerMetadata const& metadata) { - if (m_internalHooks.count(address)) { - return Error("Handler already exists at address"); + if (m_handlerHandles.count(address)) { + return Err("Handler already exists at address"); } GEODE_UNWRAP_INTO(auto handle, tulip::hook::createHandler(address, metadata)); - m_internalHooks[address] = handle; + m_handlerHandles[address] = handle; } -bool hasHandler(void* address) { - return m_internalHooks.count(address); +bool Loader::Impl::hasHandler(void* address) { + return m_handlerHandles.count(address) > 0; } Result Loader::Impl::getHandler(void* address) { - if (!m_internalHooks.count(address)) { - return Error("Handler does not exist at address"); + if (!m_handlerHandles.count(address)) { + return Err("Handler does not exist at address"); } - return Ok(m_internalHooks[address]); + return Ok(m_handlerHandles[address]); } Result<> Loader::Impl::removeHandler(void* address) { - if (!m_internalHooks.count(address)) { - return Error("Handler does not exist at address"); + if (!m_handlerHandles.count(address)) { + return Err("Handler does not exist at address"); } - auto handle = m_internalHooks[address]; - tulip::hook::removeHandler(handle); - m_internalHooks.erase(address); + auto handle = m_handlerHandles[address]; + GEODE_UNWRAP(tulip::hook::removeHandler(handle)); + m_handlerHandles.erase(address); } diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp index 944fe651..2ed491b8 100644 --- a/loader/src/loader/LoaderImpl.hpp +++ b/loader/src/loader/LoaderImpl.hpp @@ -60,7 +60,7 @@ public: std::vector> m_internalHooks; bool m_readyToHook = false; - std::unordered_set m_handlerHandles; + std::unordered_map m_handlerHandles; Result<> createHandler(void* address, tulip::hook::HandlerMetadata const& metadata); bool hasHandler(void* address); diff --git a/loader/src/loader/Patch.cpp b/loader/src/loader/Patch.cpp index 59f6e6d2..8ff91e7e 100644 --- a/loader/src/loader/Patch.cpp +++ b/loader/src/loader/Patch.cpp @@ -4,11 +4,11 @@ USE_GEODE_NAMESPACE(); bool Patch::apply() { - return tulip::hook::write_memory(m_address, m_patch.data(), m_patch.size()); + return bool(tulip::hook::writeMemory(m_address, m_patch.data(), m_patch.size())); } bool Patch::restore() { - return tulip::hook::write_memory(m_address, m_original.data(), m_original.size()); + return bool(tulip::hook::writeMemory(m_address, m_original.data(), m_original.size())); } nlohmann::json Patch::getRuntimeInfo() const { From 5c9066618dea09ca5835ca236980fcf27b8b5b0d Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 12 Dec 2022 19:41:42 +0300 Subject: [PATCH 03/31] add debug texts --- loader/src/loader/Hook.cpp | 10 +++++----- loader/src/loader/Mod.cpp | 3 ++- loader/src/main.cpp | 2 ++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/loader/src/loader/Hook.cpp b/loader/src/loader/Hook.cpp index e9f3e9fd..528d9a33 100644 --- a/loader/src/loader/Hook.cpp +++ b/loader/src/loader/Hook.cpp @@ -45,7 +45,7 @@ tulip::hook::HookMetadata Hook::getHookMetadata() const { } void Hook::setHookMetadata(tulip::hook::HookMetadata const& metadata) { - m_impl->setHookMetadata(metadata); + return m_impl->setHookMetadata(metadata); } int32_t Hook::getPriority() const { @@ -53,7 +53,7 @@ int32_t Hook::getPriority() const { } void Hook::setPriority(int32_t priority) { - m_impl->setPriority(priority); + return m_impl->setPriority(priority); } bool Hook::getAutoEnable() const { @@ -61,12 +61,12 @@ bool Hook::getAutoEnable() const { } void Hook::setAutoEnable(bool autoEnable) { - m_impl->setAutoEnable(autoEnable); + return m_impl->setAutoEnable(autoEnable); } Result<> Hook::enable() { - m_impl->enable(); + return m_impl->enable(); } Result<> Hook::disable() { - m_impl->disable(); + return m_impl->disable(); } \ No newline at end of file diff --git a/loader/src/loader/Mod.cpp b/loader/src/loader/Mod.cpp index 090dca1d..d79da427 100644 --- a/loader/src/loader/Mod.cpp +++ b/loader/src/loader/Mod.cpp @@ -407,6 +407,7 @@ bool Mod::depends(std::string const& id) const { // Hooks Result<> Mod::enableHook(Hook* hook) { + log::debug("Enabling hook {} for mod {}", (void*)hook, m_info.id); auto res = hook->enable(); if (res) m_hooks.push_back(hook); @@ -423,7 +424,7 @@ Result Mod::addHook(Hook* hook) { auto res = this->enableHook(hook); if (!res) { delete hook; - return Err("Can't create hook"); + return Err("Can't create hook: "+ res.unwrapErr()); } } } diff --git a/loader/src/main.cpp b/loader/src/main.cpp index 9694f989..95c38190 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -147,6 +147,8 @@ static auto $_ = listenForIPC("list-mods", [](IPCEvent* event) -> nlohmann::json int geodeEntry(void* platformData) { // setup internals + Loader::get()->openPlatformConsole(); + if (!Loader::get()) { LoaderImpl::get()->platformMessageBox( "Unable to Load Geode!", From 6009eb8481c874712f56f0ce186fca1d0bfa2637 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 13 Dec 2022 08:00:29 +0300 Subject: [PATCH 04/31] add tuliphook as cpm --- loader/CMakeLists.txt | 3 ++- loader/tuliphook | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 160000 loader/tuliphook diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index b144544a..2a05c88f 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -130,7 +130,8 @@ CPMAddPackage("gh:mity/md4c#e9ff661") target_include_directories(${PROJECT_NAME} PRIVATE ${md4c_SOURCE_DIR}/src) # Tulip hook (hooking) -add_subdirectory(tuliphook) +CPMAddPackage("gh:altalk23/TulipHook#92b3cca") + target_link_libraries(${PROJECT_NAME} md4c z TulipHook geode-sdk) # Use precompiled headers for faster builds diff --git a/loader/tuliphook b/loader/tuliphook deleted file mode 160000 index 92b3cca3..00000000 --- a/loader/tuliphook +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 92b3cca336285ab9028b3e7f59089e6cd215be27 From eeb4bea97a9971a83e15dadcbad8bc69c58004f9 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 13 Dec 2022 13:41:34 +0300 Subject: [PATCH 05/31] fix windows compilation --- loader/src/hooks/MessageBoxFix.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/loader/src/hooks/MessageBoxFix.cpp b/loader/src/hooks/MessageBoxFix.cpp index 794f9639..1906cad1 100644 --- a/loader/src/hooks/MessageBoxFix.cpp +++ b/loader/src/hooks/MessageBoxFix.cpp @@ -40,8 +40,10 @@ static CCEGLView* CCEGLView_CCEGLView(CCEGLView* self) { } $execute { - (void)Mod::get()->addHook<&CCEGLView_CCEGLView, Thiscall>( - "CCEGLView::CCEGLView", CCEGLVIEW_CON_ADDR + (void)Mod::get()->addHook( + CCEGLVIEW_CON_ADDR, + &CCEGLView_CCEGLView, + "CCEGLView::CCEGLView", ); } From cef0f3f3bb0c2132e0796c61a816b32c8bcd1f58 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 13 Dec 2022 16:32:49 +0300 Subject: [PATCH 06/31] hooks try to get enabled --- loader/CMakeLists.txt | 3 +-- loader/include/Geode/modify/Modify.hpp | 22 +++++++++++----------- loader/src/loader/HookImpl.cpp | 7 ++++--- loader/src/loader/Mod.cpp | 5 ++++- loader/src/main.cpp | 6 +++--- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 5af65873..46f8fcdb 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -132,7 +132,7 @@ CPMAddPackage("gh:mity/md4c#e9ff661") target_include_directories(${PROJECT_NAME} PRIVATE ${md4c_SOURCE_DIR}/src) # Tulip hook (hooking) -CPMAddPackage("gh:altalk23/TulipHook#92b3cca") +CPMAddPackage("gh:altalk23/TulipHook#5ba99a8") target_link_libraries(${PROJECT_NAME} md4c z TulipHook geode-sdk) @@ -143,7 +143,6 @@ target_precompile_headers(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Loader.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/UI.hpp" # "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Bindings.hpp" - "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Modify.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/cocos/include/cocos2d.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/cocos/extensions/cocos-ext.h" ) diff --git a/loader/include/Geode/modify/Modify.hpp b/loader/include/Geode/modify/Modify.hpp index d182ffa1..b6c341be 100644 --- a/loader/include/Geode/modify/Modify.hpp +++ b/loader/include/Geode/modify/Modify.hpp @@ -12,7 +12,7 @@ #include #define GEODE_APPLY_MODIFY_FOR_FUNCTION(addr_index, pure_index, convention, className, functionName) \ - { \ + do { \ using DerivedWrap = wrap::functionName; \ using BaseWrap = wrap::functionName; \ if constexpr (DerivedWrap::uuid != nullptr && (void*)BaseWrap::uuid != (void*)DerivedWrap::uuid) { \ @@ -22,9 +22,9 @@ DerivedWrap::value, \ #className "::" #functionName \ ); \ - BaseModify::m_hooks[FunctionUUID::value] = hook; \ + this->m_hooks[#className "::" #functionName] = hook; \ } \ - } + } while (0); namespace geode::modifier { @@ -34,25 +34,25 @@ namespace geode::modifier { template class ModifyBase { public: - std::map m_hooks; + std::map m_hooks; - template - Result getHook() { - auto uuid = FunctionUUID::value; - if (m_hooks.find(uuid) == m_hooks.end()) { + Result getHook(std::string const& name) { + if (m_hooks.find(name) == m_hooks.end()) { return Err("Hook not in this modify"); } - return m_hooks[uuid]; + return Ok(m_hooks[name]); } // unordered_map idea ModifyBase() { - this->apply(); + // i really dont want to recompile codegen + auto test = static_cast(this); + test->ModifyDerived::apply(); ModifyDerived::Derived::onModify(*this); for (auto& [uuid, hook] : m_hooks) { auto res = Mod::get()->addHook(hook); if (!res) { - log::error("Failed to add hook: {}", res.error()); + log::error("Failed to add hook {}: {}", hook->getDisplayName(), res.error()); } } } diff --git a/loader/src/loader/HookImpl.cpp b/loader/src/loader/HookImpl.cpp index cbb856f3..c2945fce 100644 --- a/loader/src/loader/HookImpl.cpp +++ b/loader/src/loader/HookImpl.cpp @@ -7,7 +7,9 @@ Hook::Impl::Impl(void* address, void* detour, std::string const& displayName, tu m_displayName(displayName), m_handlerMetadata(handlerMetadata), m_hookMetadata(hookMetadata), - m_owner(owner) {} + m_owner(owner), + m_enabled(false), + m_autoEnable(true) {} Hook::Impl::~Impl() { if (m_enabled) { auto res = this->disable(); @@ -46,11 +48,10 @@ Result<> Hook::Impl::enable() { if (!LoaderImpl::get()->hasHandler(m_address)) { GEODE_UNWRAP(LoaderImpl::get()->createHandler(m_address, m_handlerMetadata)); } - GEODE_UNWRAP_INTO(auto handler, LoaderImpl::get()->getHandler(m_address)); m_handle = tulip::hook::createHook(handler, m_detour, m_hookMetadata); - log::debug("Enabling hook at function {}", m_displayName); + log::debug("Enabling hook at function {} with address {}", m_displayName, m_address); m_enabled = true; } return Ok(); diff --git a/loader/src/loader/Mod.cpp b/loader/src/loader/Mod.cpp index 2de8c682..dd2a009f 100644 --- a/loader/src/loader/Mod.cpp +++ b/loader/src/loader/Mod.cpp @@ -409,9 +409,12 @@ bool Mod::depends(std::string const& id) const { // Hooks Result<> Mod::enableHook(Hook* hook) { - log::debug("Enabling hook {} for mod {}", (void*)hook, m_info.id); + log::debug("Enabling hook {} for mod {} at address {}", (void*)hook, m_info.id, (void*)hook->getAddress()); auto res = hook->enable(); if (res) m_hooks.push_back(hook); + else { + log::error("Can't enable hook {} for mod {}: {}", (void*)hook, m_info.id, res.unwrapErr()); + } return res; } diff --git a/loader/src/main.cpp b/loader/src/main.cpp index 0099ed62..8963c1d9 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -172,9 +172,9 @@ int geodeEntry(void* platformData) { log::debug("Set up loader"); - if (InternalMod::get()->getSettingValue("show-platform-console")) { - Loader::get()->openPlatformConsole(); - } + // if (InternalMod::get()->getSettingValue("show-platform-console")) { + // Loader::get()->openPlatformConsole(); + // } log::debug("Entry done."); From d7b1d9ba70782c0320fdd1b6830f4978cd944fc2 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 13 Dec 2022 18:34:09 +0300 Subject: [PATCH 07/31] fix macos tulip-hook, it works --- loader/CMakeLists.txt | 3 ++- loader/launcher/mac/Bootstrapper.cpp | 16 +++++++++++----- loader/src/main.cpp | 14 +++++++++++--- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 46f8fcdb..0db3a909 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -121,6 +121,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE if (APPLE) # For profiling target_compile_options(${PROJECT_NAME} PUBLIC "-ftime-trace") + # target_link_options(${PROJECT_NAME} PRIVATE "-Wl,-e,_dynamicInit") #set_property(TARGET ${PROJECT_NAME} PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time") endif() @@ -132,7 +133,7 @@ CPMAddPackage("gh:mity/md4c#e9ff661") target_include_directories(${PROJECT_NAME} PRIVATE ${md4c_SOURCE_DIR}/src) # Tulip hook (hooking) -CPMAddPackage("gh:altalk23/TulipHook#5ba99a8") +CPMAddPackage("gh:altalk23/TulipHook#fc1b943") target_link_libraries(${PROJECT_NAME} md4c z TulipHook geode-sdk) diff --git a/loader/launcher/mac/Bootstrapper.cpp b/loader/launcher/mac/Bootstrapper.cpp index ddbc8ce2..0fbf8642 100644 --- a/loader/launcher/mac/Bootstrapper.cpp +++ b/loader/launcher/mac/Bootstrapper.cpp @@ -14,11 +14,17 @@ void displayError(std::string alertMessage) { } void loadGeode() { - auto dylib = dlopen("Geode.dylib", RTLD_LAZY); - if (dylib) return; - - displayError(std::string("Couldn't open Geode: ") + dlerror()); - + auto dylib = dlopen("Geode.dylib", RTLD_NOW); + if (!dylib) { + displayError(std::string("Couldn't load Geode: ") + dlerror()); + return; + } + auto trigger = dlsym(dylib, "dynamicTrigger"); + if (!trigger) { + displayError(std::string("Couldn't start Geode: ") + dlerror()); + return; + } + reinterpret_cast(trigger)(); return; } diff --git a/loader/src/main.cpp b/loader/src/main.cpp index 8963c1d9..eee44e0d 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -26,7 +26,7 @@ std::length_error::~length_error() _NOEXCEPT {} // do not ask... // from dynamic to static thats why she needs to define it // this is what old versions does to a silly girl -__attribute__((constructor)) void _entry() { +void dynamicEntry() { auto dylib = dlopen("GeodeBootstrapper.dylib", RTLD_NOLOAD); dlclose(dylib); @@ -54,6 +54,13 @@ __attribute__((constructor)) void _entry() { geodeEntry(nullptr); } +extern "C" __attribute__((visibility("default"))) void dynamicTrigger() { + std::thread(&dynamicEntry).detach(); +} + +// remove when we can figure out how to not remove it +auto dynamicTriggerRef = &dynamicTrigger; + #elif defined(GEODE_IS_WINDOWS) #include @@ -160,11 +167,12 @@ int geodeEntry(void* platformData) { } // set up loader, load mods, etc. - if (!LoaderImpl::get()->setup()) { + auto setupRes = LoaderImpl::get()->setup(); + if (!setupRes) { LoaderImpl::get()->platformMessageBox( "Unable to Load Geode!", "There was an unknown fatal error setting up " - "the loader and Geode can not be loaded." + "the loader and Geode can not be loaded." + setupRes.unwrapErr() ); LoaderImpl::get()->reset(); return 1; From 0c506ea46caf437950565499e1e65a5f6df2fb8a Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 13 Dec 2022 20:44:56 +0300 Subject: [PATCH 08/31] fix cvs --- loader/CMakeLists.txt | 2 +- loader/src/loader/LoaderImpl.cpp | 2 ++ loader/src/utils/web.cpp | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 0db3a909..78db9a59 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -133,7 +133,7 @@ CPMAddPackage("gh:mity/md4c#e9ff661") target_include_directories(${PROJECT_NAME} PRIVATE ${md4c_SOURCE_DIR}/src) # Tulip hook (hooking) -CPMAddPackage("gh:altalk23/TulipHook#fc1b943") +CPMAddPackage("gh:altalk23/TulipHook#ecbe8d7") target_link_libraries(${PROJECT_NAME} md4c z TulipHook geode-sdk) diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index 594d198c..1abe63cb 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -357,6 +357,7 @@ void Loader::Impl::refreshModsList() { // UI can be loaded now m_earlyLoadFinished = true; + m_earlyLoadFinishedCV.notify_all(); // load the rest of the mods for (auto& mod : m_modsToLoad) { @@ -378,6 +379,7 @@ void Loader::Impl::updateAllDependencies() { void Loader::Impl::waitForModsToBeLoaded() { auto lock = std::unique_lock(m_earlyLoadFinishedMutex); + log::debug("Waiting for mods to be loaded... {}", bool(m_earlyLoadFinished)); m_earlyLoadFinishedCV.wait(lock, [this] { return bool(m_earlyLoadFinished); }); diff --git a/loader/src/utils/web.cpp b/loader/src/utils/web.cpp index 3a183658..0cb110fa 100644 --- a/loader/src/utils/web.cpp +++ b/loader/src/utils/web.cpp @@ -329,10 +329,12 @@ void SentAsyncWebRequest::Impl::cancel() { void SentAsyncWebRequest::Impl::pause() { m_paused = true; + m_statusCV.notify_all(); } void SentAsyncWebRequest::Impl::resume() { m_paused = false; + m_statusCV.notify_all(); } bool SentAsyncWebRequest::Impl::finished() const { From 641c56e7beb7151314eb22117e3c82d2e46ab43c Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Wed, 14 Dec 2022 16:01:01 +0300 Subject: [PATCH 09/31] fix merge artifacts as usual --- loader/CMakeLists.txt | 2 +- loader/src/loader/HookImpl.hpp | 2 +- loader/src/loader/LoaderImpl.cpp | 15 --------------- loader/src/loader/LoaderImpl.hpp | 2 -- loader/src/loader/ModImpl.cpp | 13 +++++++++---- 5 files changed, 11 insertions(+), 23 deletions(-) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 62fd9437..a76fec4c 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -138,7 +138,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE ${md4c_SOURCE_DIR}/src) # Tulip hook (hooking) CPMAddPackage("gh:altalk23/TulipHook#ecbe8d7") -target_link_libraries(${PROJECT_NAME} md4c z TulipHook geode-sdk) +target_link_libraries(${PROJECT_NAME} md4c z TulipHook geode-sdk re2) # Use precompiled headers for faster builds target_precompile_headers(${PROJECT_NAME} PRIVATE diff --git a/loader/src/loader/HookImpl.hpp b/loader/src/loader/HookImpl.hpp index fd79bc1a..5cd891c9 100644 --- a/loader/src/loader/HookImpl.hpp +++ b/loader/src/loader/HookImpl.hpp @@ -5,7 +5,7 @@ #include #include // #include -#include "InternalMod.hpp" +#include "ModImpl.hpp" #include diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index 442c63a2..bde9cc8d 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -608,21 +608,6 @@ void Loader::Impl::releaseNextMod() { m_nextModLock.unlock(); } -Result<> Loader::Impl::setupInternalMod() { - this->provideNextMod(InternalMod::get()); - (void)Mod::get(); - m_nextModLock.unlock(); - - InternalMod::get()->setModInfo(); - - auto sett = Mod::get()->loadData(); - if (!sett) { - log::error("{}", sett.unwrapErr()); - } - - return Ok(); -} - Result<> Loader::Impl::createHandler(void* address, tulip::hook::HandlerMetadata const& metadata) { if (m_handlerHandles.count(address)) { diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp index 3c1aef09..ee715655 100644 --- a/loader/src/loader/LoaderImpl.hpp +++ b/loader/src/loader/LoaderImpl.hpp @@ -61,8 +61,6 @@ namespace geode { std::mutex m_nextModAccessMutex; Mod* m_nextMod = nullptr; - Result<> setupInternalMod(); - void provideNextMod(Mod* mod); Mod* takeNextMod(); void releaseNextMod(); diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index b0de1ef1..3867a8f1 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -481,6 +481,9 @@ bool Mod::Impl::depends(std::string const& id) const { Result<> Mod::Impl::enableHook(Hook* hook) { auto res = hook->enable(); if (res) m_hooks.push_back(hook); + else { + log::error("Can't enable hook {} for mod {}: {}", m_info.id, res.unwrapErr()); + } return res; } @@ -491,10 +494,12 @@ Result<> Mod::Impl::disableHook(Hook* hook) { Result Mod::Impl::addHook(Hook* hook) { if (LoaderImpl::get()->isReadyToHook()) { - auto res = this->enableHook(hook); - if (!res) { - delete hook; - return Err("Can't create hook"); + if (hook->getAutoEnable()) { + auto res = this->enableHook(hook); + if (!res) { + delete hook; + return Err("Can't create hook: "+ res.unwrapErr()); + } } } else { From 1bdc8f408c33b195186b154b118f55cb058eafc9 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Wed, 14 Dec 2022 17:17:52 +0300 Subject: [PATCH 10/31] Update TulipHook and fix some really minor stuff --- CMakeLists.txt | 1 + entry.cpp | 14 +++++++++++++- loader/CMakeLists.txt | 4 ++-- loader/include/Geode/loader/Event.hpp | 3 ++- loader/include/Geode/loader/Log.hpp | 2 +- loader/include/Geode/loader/Mod.hpp | 10 ---------- loader/include/Geode/utils/general.hpp | 2 +- loader/src/hooks/MessageBoxFix.cpp | 2 +- loader/src/platform/mac/Cocos2d.cpp | 2 +- 9 files changed, 22 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e61ec9c5..a5134311 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,6 +126,7 @@ elseif(EXISTS ${GEODE_PLATFORM_BIN_PATH}) target_precompile_headers(${PROJECT_NAME} INTERFACE "${GEODE_LOADER_PATH}/include/Geode/DefaultInclude.hpp" "${GEODE_LOADER_PATH}/include/Geode/Loader.hpp" + "${GEODE_LOADER_PATH}/include/Geode/Utils.hpp" # please stop adding modify here its not here because it makes windows compilation take longer than geode 1.0 release date "${GEODE_LOADER_PATH}/include/Geode/UI.hpp" "${GEODE_LOADER_PATH}/include/Geode/cocos/include/cocos2d.h" diff --git a/entry.cpp b/entry.cpp index a4679fe6..cd4cc17d 100644 --- a/entry.cpp +++ b/entry.cpp @@ -1,5 +1,17 @@ -#include #include +#include + +namespace geode { + /** + * To bypass the need for cyclic dependencies, + * this function does the exact same as Mod::get() + * However, it can be externed, unlike Mod::get() + * @returns Same thing Mod::get() returns + */ + Mod* getMod() { + return Mod::get(); + } +} namespace { // to make sure the instance is set into the sharedMod<> in load time diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index a76fec4c..7c4093eb 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -136,14 +136,14 @@ CPMAddPackage("gh:google/re2#954656f") target_include_directories(${PROJECT_NAME} PRIVATE ${md4c_SOURCE_DIR}/src) # Tulip hook (hooking) -CPMAddPackage("gh:altalk23/TulipHook#ecbe8d7") +CPMAddPackage("gh:altalk23/TulipHook#2a97005") target_link_libraries(${PROJECT_NAME} md4c z TulipHook geode-sdk re2) # Use precompiled headers for faster builds target_precompile_headers(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/DefaultInclude.hpp" - # "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Utils.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Utils.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Loader.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/UI.hpp" # "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Bindings.hpp" diff --git a/loader/include/Geode/loader/Event.hpp b/loader/include/Geode/loader/Event.hpp index 5dbbe220..d63eb2ac 100644 --- a/loader/include/Geode/loader/Event.hpp +++ b/loader/include/Geode/loader/Event.hpp @@ -1,7 +1,6 @@ #pragma once #include "../utils/casts.hpp" -#include "Mod.hpp" #include #include @@ -11,6 +10,8 @@ namespace geode { class Mod; class Event; + Mod* getMod(); + enum class ListenerResult { Propagate, Stop diff --git a/loader/include/Geode/loader/Log.hpp b/loader/include/Geode/loader/Log.hpp index 8d48c0ed..938ae7a3 100644 --- a/loader/include/Geode/loader/Log.hpp +++ b/loader/include/Geode/loader/Log.hpp @@ -15,7 +15,7 @@ namespace geode { #pragma warning(disable : 4251) class Mod; - inline Mod* getMod(); + Mod* getMod(); namespace log { using log_clock = std::chrono::system_clock; diff --git a/loader/include/Geode/loader/Mod.hpp b/loader/include/Geode/loader/Mod.hpp index f235e325..d44773ef 100644 --- a/loader/include/Geode/loader/Mod.hpp +++ b/loader/include/Geode/loader/Mod.hpp @@ -336,16 +336,6 @@ namespace geode { friend class ModImpl; }; - - /** - * To bypass the need for cyclic dependencies, - * this function does the exact same as Mod::get() - * However, it can be externed, unlike Mod::get() - * @returns Same thing Mod::get() returns - */ - inline GEODE_HIDDEN Mod* getMod() { - return Mod::get(); - } } inline char const* operator"" _spr(char const* str, size_t) { diff --git a/loader/include/Geode/utils/general.hpp b/loader/include/Geode/utils/general.hpp index dffba00e..2013d493 100644 --- a/loader/include/Geode/utils/general.hpp +++ b/loader/include/Geode/utils/general.hpp @@ -23,7 +23,7 @@ namespace geode { using ByteVector = std::vector; template - ByteVector to_byte_array(T const& a) { + ByteVector toByteArray(T const& a) { ByteVector out; out.resize(sizeof(T)); std::memcpy(out.data(), &a, sizeof(T)); diff --git a/loader/src/hooks/MessageBoxFix.cpp b/loader/src/hooks/MessageBoxFix.cpp index 1906cad1..d77f1424 100644 --- a/loader/src/hooks/MessageBoxFix.cpp +++ b/loader/src/hooks/MessageBoxFix.cpp @@ -34,7 +34,7 @@ static CCEGLView* CCEGLView_CCEGLView(CCEGLView* self) { reinterpret_cast(CCEGLVIEW_CON_ADDR)(self); static auto p = Mod::get()->patch( reinterpret_cast(geode::base::getCocos() + 0x19feec), - to_byte_array(&fixedErrorHandler) + toByteArray(&fixedErrorHandler) ); return self; } diff --git a/loader/src/platform/mac/Cocos2d.cpp b/loader/src/platform/mac/Cocos2d.cpp index 16af07d2..d0a366d8 100644 --- a/loader/src/platform/mac/Cocos2d.cpp +++ b/loader/src/platform/mac/Cocos2d.cpp @@ -662,7 +662,7 @@ CCObject* CCArray::randomObject() return NULL; } - float r = CCRANDOM_0_1(); + float r = ((float)rand()/(float)RAND_MAX); if (r == 1) // to prevent from accessing data-arr[data->num], out of range. { From ac40e4c8fbba3e10d5a4446bfed7f2f30f726b71 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Wed, 14 Dec 2022 17:25:25 +0300 Subject: [PATCH 11/31] fix tuliphook result and windows messageboxfix --- loader/CMakeLists.txt | 2 +- loader/src/hooks/MessageBoxFix.cpp | 19 ++----------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 7c4093eb..75b7b3b9 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -136,7 +136,7 @@ CPMAddPackage("gh:google/re2#954656f") target_include_directories(${PROJECT_NAME} PRIVATE ${md4c_SOURCE_DIR}/src) # Tulip hook (hooking) -CPMAddPackage("gh:altalk23/TulipHook#2a97005") +CPMAddPackage("gh:altalk23/TulipHook#2347311") target_link_libraries(${PROJECT_NAME} md4c z TulipHook geode-sdk re2) diff --git a/loader/src/hooks/MessageBoxFix.cpp b/loader/src/hooks/MessageBoxFix.cpp index d77f1424..fbe366af 100644 --- a/loader/src/hooks/MessageBoxFix.cpp +++ b/loader/src/hooks/MessageBoxFix.cpp @@ -7,14 +7,11 @@ #include USE_GEODE_NAMESPACE(); -using geode::core::meta::x86::Thiscall; // for some reason RobTop uses MessageBoxW in his GLFW error handler. // no one knows how this is possible (he passes char* to wchar_t*). // so anyway, here's a fix for it -static auto CCEGLVIEW_CON_ADDR = reinterpret_cast(base::getCocos() + 0xc2860); - static void __cdecl fixedErrorHandler(int code, char const* description) { log::error("GLFW Error {}: {}", code, description); MessageBoxA( @@ -28,23 +25,11 @@ static void __cdecl fixedErrorHandler(int code, char const* description) { ); } -static CCEGLView* CCEGLView_CCEGLView(CCEGLView* self) { - // you will never have to make a manual hook with Geode again, they said - // it will be fun, they said - reinterpret_cast(CCEGLVIEW_CON_ADDR)(self); - static auto p = Mod::get()->patch( +$execute { + (void)Mod::get()->patch( reinterpret_cast(geode::base::getCocos() + 0x19feec), toByteArray(&fixedErrorHandler) ); - return self; -} - -$execute { - (void)Mod::get()->addHook( - CCEGLVIEW_CON_ADDR, - &CCEGLView_CCEGLView, - "CCEGLView::CCEGLView", - ); } #endif From a15e8cb30fa900dba33708353af22fff617ff071 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Fri, 13 Jan 2023 09:12:50 +0300 Subject: [PATCH 12/31] temporarily comment out trysavegame hook --- CMakeLists.txt | 5 ++++- loader/CMakeLists.txt | 4 +--- loader/src/hooks/save.cpp | 22 +++++++++++----------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82a4c4bd..3d186523 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,10 @@ target_link_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/lo CPMAddPackage("gh:fmtlib/fmt#9.1.0") CPMAddPackage("gh:gulrak/filesystem#3e5b930") -target_link_libraries(${PROJECT_NAME} INTERFACE ghc_filesystem fmt) +# Tulip hook (hooking) +CPMAddPackage("gh:altalk23/TulipHook#d911a46") + +target_link_libraries(${PROJECT_NAME} INTERFACE ghc_filesystem fmt TulipHookInclude) if (NOT EXISTS ${GEODE_BIN_PATH}) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index c6cf2e51..cddae67b 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -135,11 +135,9 @@ CPMAddPackage("gh:google/re2#954656f") target_include_directories(${PROJECT_NAME} PRIVATE ${md4c_SOURCE_DIR}/src) -# Tulip hook (hooking) -CPMAddPackage("gh:altalk23/TulipHook#2347311") - target_link_libraries(${PROJECT_NAME} md4c z TulipHook geode-sdk re2) + # Use precompiled headers for faster builds if (NOT GEODE_DISABLE_PRECOMPILED_HEADERS) target_precompile_headers(${PROJECT_NAME} PRIVATE diff --git a/loader/src/hooks/save.cpp b/loader/src/hooks/save.cpp index a0db4471..248caca9 100644 --- a/loader/src/hooks/save.cpp +++ b/loader/src/hooks/save.cpp @@ -4,17 +4,17 @@ USE_GEODE_NAMESPACE(); #include -struct SaveLoader : Modify { - void trySaveGame() { - log::info("Saving..."); +// struct SaveLoader : Modify { +// void trySaveGame() { +// log::info("Saving..."); - auto r = Loader::get()->saveData(); - if (!r) { - log::info("{}", r.unwrapErr()); - } +// auto r = Loader::get()->saveData(); +// if (!r) { +// log::info("{}", r.unwrapErr()); +// } - log::info("Saved"); +// log::info("Saved"); - return AppDelegate::trySaveGame(); - } -}; +// return AppDelegate::trySaveGame(); +// } +// }; From e47a5b4e2771fca6c35d8e9898cb232224e6cd89 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 14 Jan 2023 19:31:56 +0300 Subject: [PATCH 13/31] fix the trysavegame hook --- CMakeLists.txt | 2 +- loader/src/hooks/save.cpp | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d186523..2df66002 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,7 +104,7 @@ CPMAddPackage("gh:fmtlib/fmt#9.1.0") CPMAddPackage("gh:gulrak/filesystem#3e5b930") # Tulip hook (hooking) -CPMAddPackage("gh:altalk23/TulipHook#d911a46") +CPMAddPackage("gh:altalk23/TulipHook#298d572") target_link_libraries(${PROJECT_NAME} INTERFACE ghc_filesystem fmt TulipHookInclude) diff --git a/loader/src/hooks/save.cpp b/loader/src/hooks/save.cpp index 248caca9..a0db4471 100644 --- a/loader/src/hooks/save.cpp +++ b/loader/src/hooks/save.cpp @@ -4,17 +4,17 @@ USE_GEODE_NAMESPACE(); #include -// struct SaveLoader : Modify { -// void trySaveGame() { -// log::info("Saving..."); +struct SaveLoader : Modify { + void trySaveGame() { + log::info("Saving..."); -// auto r = Loader::get()->saveData(); -// if (!r) { -// log::info("{}", r.unwrapErr()); -// } + auto r = Loader::get()->saveData(); + if (!r) { + log::info("{}", r.unwrapErr()); + } -// log::info("Saved"); + log::info("Saved"); -// return AppDelegate::trySaveGame(); -// } -// }; + return AppDelegate::trySaveGame(); + } +}; From a1be695aab18b9aa22ac8da82b38a4a9d27646a5 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 14 Jan 2023 22:24:12 +0300 Subject: [PATCH 14/31] replace modify checking implementation i got distracted --- cmake/Platform.cmake | 2 +- codegen/src/BindingGen.cpp | 11 +- codegen/src/Main.cpp | 2 +- codegen/src/ModifyGen.cpp | 89 +++++++---- codegen/src/SourceGen.cpp | 6 +- loader/CMakeLists.txt | 1 - .../Geode/cocos/label_nodes/CCLabelTTF.h | 1 - .../Geode/cocos/platform/CCPlatformMacros.h | 29 ++-- .../include/Geode/modify/AsStaticFunction.hpp | 37 +++++ loader/include/Geode/modify/Modify.hpp | 60 ++++++-- loader/include/Geode/modify/Traits.hpp | 143 +++++++++++++++++- loader/include/Geode/modify/Wrapper.hpp | 81 ---------- loader/src/ids/CreatorLayer.cpp | 2 +- loader/src/ids/LevelBrowserLayer.cpp | 2 +- loader/src/ids/LevelSettingsLayer.cpp | 24 ++- 15 files changed, 334 insertions(+), 156 deletions(-) create mode 100644 loader/include/Geode/modify/AsStaticFunction.hpp delete mode 100644 loader/include/Geode/modify/Wrapper.hpp diff --git a/cmake/Platform.cmake b/cmake/Platform.cmake index 9e20c189..61860272 100644 --- a/cmake/Platform.cmake +++ b/cmake/Platform.cmake @@ -32,7 +32,7 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "MacOS") ) target_link_libraries(${PROJECT_NAME} INTERFACE curl "-framework Cocoa") - target_compile_options(${PROJECT_NAME} INTERFACE -fms-extensions -Wno-deprecated -Wno-ignored-attributes -Os #[[-flto]] -fvisibility=internal) + target_compile_options(${PROJECT_NAME} INTERFACE -fms-extensions #[[-Wno-deprecated]] -Wno-ignored-attributes -Os #[[-flto]] -fvisibility=internal) set(GEODE_PLATFORM_BINARY "Geode.dylib") diff --git a/codegen/src/BindingGen.cpp b/codegen/src/BindingGen.cpp index 2f4b4e22..c41d51d4 100644 --- a/codegen/src/BindingGen.cpp +++ b/codegen/src/BindingGen.cpp @@ -41,14 +41,17 @@ public: char const* function_definition = R"GEN({docs} {static}{virtual}{return_type} {function_name}({parameters}){const}; )GEN"; - char const* error_definition = R"GEN( template + char const* error_definition = R"GEN( + #ifdef GEODE_WARN_INCORRECT_MEMBERS + [[deprecated("Function is not implemented - will throw at runtime!!!")]] + #endif {static}{return_type} {function_name}({parameters}){const}{{ - static_assert(T, "Implement {class_name}::{function_name}"); + throw std::runtime_error("Use of undefined function " + GEODE_PRETTY_FUNCTION); }} )GEN"; char const* error_definition_virtual = R"GEN( - #ifndef GEODE_DONT_WARN_INCORRECT_MEMBERS + #ifdef GEODE_WARN_INCORRECT_MEMBERS [[deprecated("Use of undefined virtual function - will crash at runtime!!!")]] #endif {virtual}{return_type} {function_name}({parameters}){const}{{ @@ -60,7 +63,7 @@ public: )GEN"; char const* warn_offset_member = R"GEN( - #ifndef GEODE_DONT_WARN_INCORRECT_MEMBERS + #ifdef GEODE_WARN_INCORRECT_MEMBERS [[deprecated("Member placed incorrectly - will crash at runtime!!!")]] #endif )GEN"; diff --git a/codegen/src/Main.cpp b/codegen/src/Main.cpp index 54a74b74..1ab72db0 100644 --- a/codegen/src/Main.cpp +++ b/codegen/src/Main.cpp @@ -33,7 +33,7 @@ int main(int argc, char** argv) try { writeFile(writeDir / "GeneratedAddress.hpp", generateAddressHeader(root)); writeFile(writeDir / "GeneratedModify.hpp", generateModifyHeader(root, writeDir / "modify")); - writeFile(writeDir / "GeneratedWrapper.hpp", generateWrapperHeader(root)); + // writeFile(writeDir / "GeneratedWrapper.hpp", generateWrapperHeader(root)); writeFile(writeDir / "GeneratedType.hpp", generateTypeHeader(root)); writeFile(writeDir / "GeneratedBinding.hpp", generateBindingHeader(root, writeDir / "binding")); writeFile(writeDir / "GeneratedPredeclare.hpp", generatePredeclareHeader(root)); diff --git a/codegen/src/ModifyGen.cpp b/codegen/src/ModifyGen.cpp index c3ccee75..12b26e3c 100644 --- a/codegen/src/ModifyGen.cpp +++ b/codegen/src/ModifyGen.cpp @@ -6,29 +6,16 @@ namespace { namespace format_strings { - char const* wrap_start = R"GEN( - namespace wrap { -)GEN"; - - char const* wrap_declare_identifier = R"GEN( - #ifndef GEODE_WRAP_{function_name} - #define GEODE_WRAP_{function_name} - GEODE_WRAPPER_FOR_IDENTIFIER({function_name}) - #endif -)GEN"; - - char const* wrap_end = R"GEN( - } -)GEN"; - // requires: class_name + // requires: class_name, class_include char const* modify_start = R"GEN(#pragma once #include #include #include +{class_include} using namespace geode::modifier; - namespace geode::modifier {{ - {wrap} + {statics} + template struct ModifyDerive : ModifyBase> {{ using BaseModify = ModifyBase>; @@ -38,11 +25,24 @@ namespace geode::modifier {{ void apply() override {{ using namespace geode::core::meta; +)GEN"; + + char const* statics_declare_identifier = R"GEN( + #ifndef GEODE_STATICS_{function_name} + #define GEODE_STATICS_{function_name} + GEODE_AS_STATIC_FUNCTION({function_name}) + #endif )GEN"; // requires: index, class_name, arg_types, function_name, raw_arg_types, non_virtual char const* apply_function = R"GEN( - GEODE_APPLY_MODIFY_FOR_FUNCTION({addr_index}, {pure_index}, {function_convention}, {class_name}, {function_name}))GEN"; + GEODE_APPLY_MODIFY_FOR_FUNCTION({addr_index}, {function_convention}, {class_name}, {function_name}, {parameter_types}))GEN"; + + char const* apply_constructor = R"GEN( + GEODE_APPLY_MODIFY_FOR_CONSTRUCTOR({addr_index}, {function_convention}, {class_name}, {parameter_types}))GEN"; + + char const* apply_destructor = R"GEN( + GEODE_APPLY_MODIFY_FOR_DESTRUCTOR({addr_index}, {function_convention}, {class_name}))GEN"; char const* modify_end = R"GEN( } @@ -68,45 +68,70 @@ std::string generateModifyHeader(Root& root, ghc::filesystem::path const& single output += fmt::format(format_strings::modify_include, fmt::arg("file_name", filename)); std::string single_output; - std::string wrap; - // wrap - wrap += format_strings::wrap_start; + std::string class_include; + + if (c.name.find("cocos2d::extension") != std::string::npos) { + class_include = "#include "; + } + else if (c.name.find("cocos2d") != std::string::npos) { + class_include = "#include "; + } + else { + class_include = fmt::format( + "#include ", + fmt::arg("class_name", codegen::getUnqualifiedClassName(c.name)) + ); + } + + std::string statics; std::set used; for (auto& f : c.fields) { if (auto fn = f.get_fn()) { if (fn->type == FunctionType::Normal && !used.count(fn->name)) { used.insert(fn->name); - wrap += fmt::format( - format_strings::wrap_declare_identifier, fmt::arg("function_name", fn->name) + statics += fmt::format( + format_strings::statics_declare_identifier, fmt::arg("function_name", fn->name) ); } } } - wrap += format_strings::wrap_end; single_output += fmt::format( - format_strings::modify_start, fmt::arg("class_name", c.name), fmt::arg("wrap", wrap) + format_strings::modify_start, + fmt::arg("statics", statics), + fmt::arg("class_name", c.name), + fmt::arg("class_include", class_include) ); // modify for (auto& f : c.fields) { if (codegen::getStatus(f) != BindStatus::Unbindable) { auto begin = f.get_fn(); + auto func = TypeBank::makeFunc(*begin, c.name); - std::string function_name; + std::string format_string; switch (begin->type) { - case FunctionType::Normal: function_name = begin->name; break; - case FunctionType::Ctor: function_name = "constructor"; break; - case FunctionType::Dtor: function_name = "destructor"; break; + case FunctionType::Normal: + format_string = format_strings::apply_function; + break; + case FunctionType::Ctor: + format_string = format_strings::apply_constructor; + break; + case FunctionType::Dtor: + format_string = format_strings::apply_destructor; + break; } single_output += fmt::format( - format_strings::apply_function, fmt::arg("addr_index", f.field_id), + format_string, + fmt::arg("addr_index", f.field_id), fmt::arg("pure_index", bank.getPure(*begin, c.name)), - fmt::arg("class_name", c.name), fmt::arg("function_name", function_name), - fmt::arg("function_convention", codegen::getModifyConvention(f)) + fmt::arg("class_name", c.name), + fmt::arg("function_name", begin->name), + fmt::arg("function_convention", codegen::getModifyConvention(f)), + fmt::arg("parameter_types", fmt::join(func.parameter_types, ", ")) ); } } diff --git a/codegen/src/SourceGen.cpp b/codegen/src/SourceGen.cpp index 1db88533..1120b28e 100644 --- a/codegen/src/SourceGen.cpp +++ b/codegen/src/SourceGen.cpp @@ -18,14 +18,14 @@ using namespace geode::modifier; // types )CAC"; char const* declare_member = R"GEN( -types::ret{ret_index} {class_name}::{function_name}({parameters}){const} {{ +auto {class_name}::{function_name}({parameters}){const} -> decltype({function_name}({arguments})) {{ auto func = Function({{addresses::address{addr_index}()}}); return func(this{parameter_comma}{arguments}); }} )GEN"; char const* declare_virtual = R"GEN( -types::ret{ret_index} {class_name}::{function_name}({parameters}){const} {{ +auto {class_name}::{function_name}({parameters}){const} -> decltype({function_name}({arguments})) {{ auto self = addresser::thunkAdjust((types::member{member_index})(&{class_name}::{function_name}), this); auto func = Function({{addresses::address{addr_index}()}}); return func(self{parameter_comma}{arguments}); @@ -33,7 +33,7 @@ types::ret{ret_index} {class_name}::{function_name}({parameters}){const} {{ )GEN"; char const* declare_static = R"GEN( -types::ret{ret_index} {class_name}::{function_name}({parameters}){const} {{ +auto {class_name}::{function_name}({parameters}){const} -> decltype({function_name}({arguments})) {{ auto func = Function({{addresses::address{addr_index}()}}); return func({arguments}); }} diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index cddae67b..e97bcdfd 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -146,7 +146,6 @@ if (NOT GEODE_DISABLE_PRECOMPILED_HEADERS) "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Loader.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/UI.hpp" # "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Bindings.hpp" - "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Modify.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/cocos/include/cocos2d.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/cocos/extensions/cocos-ext.h" ) diff --git a/loader/include/Geode/cocos/label_nodes/CCLabelTTF.h b/loader/include/Geode/cocos/label_nodes/CCLabelTTF.h index c366924a..721d8b60 100644 --- a/loader/include/Geode/cocos/label_nodes/CCLabelTTF.h +++ b/loader/include/Geode/cocos/label_nodes/CCLabelTTF.h @@ -57,7 +57,6 @@ NS_CC_BEGIN class CC_DLL CCLabelTTF : public CCSprite, public CCLabelProtocol { - GEODE_FRIEND_MODIFY GEODE_FRIEND_MODIFY public: /** diff --git a/loader/include/Geode/cocos/platform/CCPlatformMacros.h b/loader/include/Geode/cocos/platform/CCPlatformMacros.h index 3c2cb642..fa0885bc 100644 --- a/loader/include/Geode/cocos/platform/CCPlatformMacros.h +++ b/loader/include/Geode/cocos/platform/CCPlatformMacros.h @@ -113,20 +113,25 @@ It's new in cocos2d-x since v0.99.5 * macro. */ class GeodeNodeMetadata; -namespace geode { - struct modify; - namespace modifier { - struct addresses; - struct types; + +namespace geode { + struct modify; + + namespace modifier { + struct types; class FieldContainer; - } + + template + class ModifyDerive; + } } -#define GEODE_FRIEND_MODIFY GEODE_ADD(\ - friend struct ::geode::modify;\ - friend struct ::geode::modifier::addresses;\ - friend struct ::geode::modifier::types;\ - friend class ::GeodeNodeMetadata;\ -) + +#define GEODE_FRIEND_MODIFY \ + friend struct ::geode::modify; \ + template \ + friend class ::geode::modifier::ModifyDerive; \ + friend struct ::geode::modifier::types; \ + friend class ::GeodeNodeMetadata; #define GEODE_ADD(...) __VA_ARGS__ #ifdef __cplusplus diff --git a/loader/include/Geode/modify/AsStaticFunction.hpp b/loader/include/Geode/modify/AsStaticFunction.hpp new file mode 100644 index 00000000..b23f70fe --- /dev/null +++ b/loader/include/Geode/modify/AsStaticFunction.hpp @@ -0,0 +1,37 @@ +#pragma once +#include "../utils/addresser.hpp" +#include "Traits.hpp" + +namespace geode::modifier { +/** + * A helper struct that generates a static function that calls the given function. + */ +#define GEODE_AS_STATIC_FUNCTION(FunctionName_) \ + template \ + struct AsStaticFunction_##FunctionName_ { \ + template \ + struct Impl {}; \ + template \ + struct Impl { \ + static Return function(Params... params) { return Class2::FunctionName_(params...); } \ + }; \ + template \ + struct Impl { \ + static Return function(Class* self, Params... params) { \ + auto self2 = addresser::rthunkAdjust(Function, self); \ + return self2->Class2::FunctionName_(params...); \ + } \ + }; \ + template \ + struct Impl { \ + static Return function(Class const* self, Params... params) { \ + auto self2 = addresser::rthunkAdjust(Function, self); \ + return self2->Class2::FunctionName_(params...); \ + } \ + }; \ + static constexpr auto value = &Impl::function; \ + }; + + GEODE_AS_STATIC_FUNCTION(constructor) + GEODE_AS_STATIC_FUNCTION(destructor) +} diff --git a/loader/include/Geode/modify/Modify.hpp b/loader/include/Geode/modify/Modify.hpp index 48b3f733..d9db0ee6 100644 --- a/loader/include/Geode/modify/Modify.hpp +++ b/loader/include/Geode/modify/Modify.hpp @@ -1,29 +1,57 @@ #pragma once #include "../meta/meta.hpp" #include "Addresses.hpp" +#include "AsStaticFunction.hpp" #include "Field.hpp" #include "IDManager.hpp" #include "Types.hpp" -#include "Wrapper.hpp" #include #include #include #include -#define GEODE_APPLY_MODIFY_FOR_FUNCTION(addr_index, pure_index, convention, className, functionName) \ - do { \ - using DerivedWrap = wrap::functionName; \ - using BaseWrap = wrap::functionName; \ - if constexpr (DerivedWrap::uuid != nullptr && (void*)BaseWrap::uuid != (void*)DerivedWrap::uuid) { \ - auto hook = Hook::create( \ - Mod::get(), \ - reinterpret_cast(addresses::address##addr_index()), \ - DerivedWrap::value, \ - #className "::" #functionName \ - ); \ - this->m_hooks[#className "::" #functionName] = hook; \ - } \ +#define GEODE_APPLY_MODIFY_FOR_FUNCTION(AddressIndex_, Convention_, ClassName_, FunctionName_, ...) \ + do { \ + constexpr auto b = Resolve<__VA_ARGS__>::func(&Base::FunctionName_); \ + constexpr auto d = Resolve<__VA_ARGS__>::func(&Derived::FunctionName_); \ + if constexpr (Unique::different()) { \ + auto hook = Hook::create( \ + Mod::get(), \ + reinterpret_cast(addresses::address##AddressIndex_()), \ + AsStaticFunction_##FunctionName_::value, \ + #ClassName_ "::" #FunctionName_ \ + ); \ + this->m_hooks[#ClassName_ "::" #FunctionName_] = hook; \ + } \ + } while (0); + +#define GEODE_APPLY_MODIFY_FOR_CONSTRUCTOR(AddressIndex_, Convention_, ClassName_, ...) \ + do { \ + if constexpr (HasConstructor) { \ + constexpr auto d = Resolve<__VA_ARGS__>::func(&Derived::constructor); \ + auto hook = Hook::create( \ + Mod::get(), \ + reinterpret_cast(addresses::address##AddressIndex_()), \ + AsStaticFunction_##constructor::value, \ + #ClassName_ "::" #ClassName_ \ + ); \ + this->m_hooks[#ClassName_ "::" #ClassName_] = hook; \ + } \ + } while (0); + +#define GEODE_APPLY_MODIFY_FOR_DESTRUCTOR(AddressIndex_, Convention_, ClassName_) \ + do { \ + if constexpr (HasDestructor) { \ + constexpr auto d = Resolve<>::func(&Derived::destructor); \ + auto hook = Hook::create( \ + Mod::get(), \ + reinterpret_cast(addresses::address##AddressIndex_()), \ + AsStaticFunction_##destructor::value, \ + #ClassName_ "::" #ClassName_ \ + ); \ + this->m_hooks[#ClassName_ "::" #ClassName_] = hook; \ + } \ } while (0); namespace geode::modifier { @@ -87,11 +115,15 @@ namespace geode { // we already have utilities for these, which are ccdestructor // and the monostate constructor Modify() : Base(std::monostate(), sizeof(Base)) {} + ~Modify() { cocos2d::CCDestructor::lock(this) = true; } + Modify(Modify const&) = delete; Modify(Modify&&) = delete; + Modify& operator=(Modify const&) = delete; + Modify& operator=(Modify&&) = delete; modifier::FieldIntermediate m_fields; diff --git a/loader/include/Geode/modify/Traits.hpp b/loader/include/Geode/modify/Traits.hpp index b69ef3cc..9431e585 100644 --- a/loader/include/Geode/modify/Traits.hpp +++ b/loader/include/Geode/modify/Traits.hpp @@ -1,5 +1,4 @@ #pragma once -#include #include namespace geode::modifier { @@ -28,8 +27,6 @@ namespace geode::modifier { using type = FunctionType*; }; - using ::geode::core::meta::always_false; - /** * The ~unevaluated~ function that gets the appropriate * version of a function type from its return, parameters, and classes. @@ -65,4 +62,144 @@ namespace geode::modifier { public: constexpr static inline void (*value)() = &FunctionUUID::function; }; + + /** + * A type trait that removes the class from a member function pointer. + */ + template + struct RemoveClass { + using type = Func; + }; + + template + struct RemoveClass { + using type = Return(Params...); + }; + + template + struct RemoveClass { + using type = Return(Params...); + }; + + template + using RemoveClassType = typename RemoveClass::type; + + /** + * A helper struct that allows for checking if two function pointers + * are the same or different. + */ + struct Unique { + using ValueType = void(*)(...); + static constexpr auto nvalue = static_cast(nullptr); + + template + struct Impl { + static void unique(...) {}; + + static constexpr auto value = &unique; + }; + + template <> + struct Impl { + static constexpr auto value = nvalue; + }; + + template + static constexpr auto value = Impl::value; + + + /** + * Checks if two function pointers are the same. If their types are + * different, returns false. + */ + template + static constexpr auto same() { + if (!std::is_same_v, RemoveClassType>) return false; + auto v1 = value; + auto v2 = value; + if (v1 == nvalue) return false; + if (v2 == nvalue) return false; + return v1 == v2; + } + + /** + * Checks if two function pointers are different. If their types are + * different, returns false. + */ + template + static constexpr auto different() { + if (!std::is_same_v, RemoveClassType>) return false; + auto v1 = value; + auto v2 = value; + if (v1 == nvalue) return false; + if (v2 == nvalue) return false; + return v1 != v2; + } + }; + + /** + * Helps resolving an overloaded function pointer to a specific function using + * its parameter types as the hint. + */ + template + struct Resolve { + template + static constexpr auto func(Return(*ptr)(std::type_identity_t...)) { + return ptr; + } + + template + static constexpr auto func(Return(Class::*ptr)(std::type_identity_t...)) { + return ptr; + } + + template + static constexpr auto func(Return(Class::*ptr)(std::type_identity_t...) const) { + return ptr; + } + + static constexpr auto func(...) { + return Unique::nvalue; + } + }; + + /** + * A specialization for giving the variadic types as a single type with the + * function type. The return type is ignored. + */ + template + struct Resolve : Resolve { + using Resolve::func; + }; + + /** + * A type trait that checks if a class has a function called "constructor". + */ + template + concept HasConstructor = requires { + &Class::constructor; + }; + + /** + * A type trait that checks if a class has a function called "destructor". + */ + template + concept HasDestructor = requires { + &Class::destructor; + }; + + template + struct AsStaticType { + using type = FunctionType; + }; + + template + struct AsStaticType { + using type = Return(*)(Class*, Params...); + }; + + template + struct AsStaticType { + using type = Return(*)(Class const*, Params...); + }; } diff --git a/loader/include/Geode/modify/Wrapper.hpp b/loader/include/Geode/modify/Wrapper.hpp deleted file mode 100644 index 6993a90d..00000000 --- a/loader/include/Geode/modify/Wrapper.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once -#include "../utils/addresser.hpp" -#include "Traits.hpp" - -#define GEODE_WRAPPER_FOR_IDENTIFIER(identifier) \ - /* Default - function Return Class::identifier(Parameters...) does not exist */ \ - template \ - struct identifier { \ - public: \ - constexpr static inline auto value = nullptr; \ - constexpr static inline auto uuid = nullptr; \ - }; \ - /* Specialization - function Return Class::identifier(Parameters...) is a member function */ \ - template \ - struct identifier< \ - Class, Return(Parameters...), \ - std::enable_if_t(&Class::identifier))>>> { \ - private: \ - static Return wrapperImpl(Class* self, Parameters... ps) { \ - self = addresser::rthunkAdjust( \ - substitute(&Class::identifier), self \ - ); \ - return self->Class::identifier(ps...); \ - } \ - \ - public: \ - constexpr static inline auto value = &wrapperImpl; \ - constexpr static inline auto uuid = \ - FunctionUUID(&Class::identifier)>::value; \ - }; \ - /* Specialization - function Return Class::identifier(Parameters...) is a static function */ \ - template \ - struct identifier< \ - Class, Return(Parameters...), \ - std::enable_if_t< \ - std::is_pointer_v(&Class::identifier))>>> { \ - private: \ - static Return wrapperImpl(Parameters... ps) { \ - return Class::identifier(ps...); \ - } \ - \ - public: \ - constexpr static inline auto value = &wrapperImpl; \ - constexpr static inline auto uuid = \ - FunctionUUID(&Class::identifier)>::value; \ - }; - -namespace geode::modifier { - namespace wrap { - GEODE_WRAPPER_FOR_IDENTIFIER(constructor) - GEODE_WRAPPER_FOR_IDENTIFIER(destructor) - }; - - // template class Identifier, class Base, class Derived, - // class ...Types> struct PotentiallyWrongIdentifier { - - // template - // static std::true_type existsImpl(...); - - // template ::uuid == nullptr || - // Identifier::uuid == Identifier::uuid - // )) - // >> - // static std::false_type existsImpl(char); - - // template ::uuid != nullptr && - // Identifier::uuid == Identifier::uuid - // )) - // >> - // static std::false_type existsImpl(int); - - // static constexpr bool value = decltype(existsImpl(0))::value; - - // }; - -} diff --git a/loader/src/ids/CreatorLayer.cpp b/loader/src/ids/CreatorLayer.cpp index 442f4276..9e161b83 100644 --- a/loader/src/ids/CreatorLayer.cpp +++ b/loader/src/ids/CreatorLayer.cpp @@ -1,7 +1,7 @@ #include "AddIDs.hpp" #include -#include +#include #include USE_GEODE_NAMESPACE(); diff --git a/loader/src/ids/LevelBrowserLayer.cpp b/loader/src/ids/LevelBrowserLayer.cpp index d3584613..de08965e 100644 --- a/loader/src/ids/LevelBrowserLayer.cpp +++ b/loader/src/ids/LevelBrowserLayer.cpp @@ -1,7 +1,7 @@ #include "AddIDs.hpp" #include -#include +#include #include USE_GEODE_NAMESPACE(); diff --git a/loader/src/ids/LevelSettingsLayer.cpp b/loader/src/ids/LevelSettingsLayer.cpp index 3b8bd810..9da13acc 100644 --- a/loader/src/ids/LevelSettingsLayer.cpp +++ b/loader/src/ids/LevelSettingsLayer.cpp @@ -1,7 +1,7 @@ #include "AddIDs.hpp" #include -#include +#include #include USE_GEODE_NAMESPACE(); @@ -205,3 +205,25 @@ struct LevelSettingsLayerIDs : Modify return true; } }; + + + template + struct Resolve2 { + template + static constexpr auto func(Return(*ptr)(float)) { + return ptr; + } + + template + static constexpr auto func(Return(Class::*ptr)(float)) { + return ptr; + } + + template + static constexpr auto func(Return(Class::*ptr)(float) const) { + return ptr; + } + }; + +#include +constexpr auto b = Resolve2::func(&PlayerObject::runBallRotation); \ No newline at end of file From a1c7139e53c5930e0d0de07344776a19351aa308 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Jan 2023 00:45:58 +0300 Subject: [PATCH 15/31] I only changed the headers and not the sources to improve compile times a bit --- CMakeLists.txt | 12 ++- codegen/src/AddressGen.cpp | 8 +- codegen/src/BindingGen.cpp | 1 + codegen/src/Main.cpp | 2 +- codegen/src/ModifyGen.cpp | 1 + codegen/src/SourceGen.cpp | 57 ++++++++++--- loader/include/Geode/Loader.hpp | 1 - .../include/Geode/external/json/json_fwd.hpp | 79 +++++++++++++++++++ loader/include/Geode/loader/Hook.hpp | 2 +- loader/include/Geode/loader/Mod.hpp | 52 ++---------- loader/include/Geode/loader/ModInfo.hpp | 5 +- loader/include/Geode/loader/ModJsonTest.hpp | 59 ++++++++++++++ loader/include/Geode/loader/Setting.hpp | 25 +++--- .../include/Geode/loader/SettingJsonTest.hpp | 21 +++++ loader/include/Geode/loader/Types.hpp | 2 +- loader/include/Geode/modify/Addresses.hpp | 5 +- loader/include/Geode/modify/Modify.hpp | 7 +- loader/include/Geode/modify/Types.hpp | 6 +- loader/include/Geode/utils/VersionInfo.hpp | 2 +- loader/include/Geode/utils/cocos.hpp | 2 +- loader/include/Geode/utils/file.hpp | 2 +- loader/include/Geode/utils/web.hpp | 14 +--- loader/src/loader/Setting.cpp | 1 + loader/src/utils/web.cpp | 11 +++ 24 files changed, 268 insertions(+), 109 deletions(-) create mode 100644 loader/include/Geode/external/json/json_fwd.hpp create mode 100644 loader/include/Geode/loader/ModJsonTest.hpp create mode 100644 loader/include/Geode/loader/SettingJsonTest.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2df66002..d36e983b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,7 +88,13 @@ if (NOT EXISTS ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp) file(TOUCH ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp) endif() -target_sources(${PROJECT_NAME} INTERFACE ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp) +if (NOT EXISTS ${GEODE_CODEGEN_PATH}/Geode/GeneratedAddress.cpp) + make_directory(${GEODE_CODEGEN_PATH}) + make_directory(${GEODE_CODEGEN_PATH}/Geode) + file(TOUCH ${GEODE_CODEGEN_PATH}/Geode/GeneratedAddress.cpp) +endif() + +target_sources(${PROJECT_NAME} INTERFACE ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp ${GEODE_CODEGEN_PATH}/Geode/GeneratedAddress.cpp) target_include_directories(${PROJECT_NAME} INTERFACE ${GEODE_CODEGEN_PATH} @@ -131,10 +137,8 @@ elseif(EXISTS ${GEODE_PLATFORM_BIN_PATH}) target_link_libraries(${PROJECT_NAME} INTERFACE "${GEODE_PLATFORM_BIN_PATH}") target_precompile_headers(${PROJECT_NAME} INTERFACE "${GEODE_LOADER_PATH}/include/Geode/DefaultInclude.hpp" - "${GEODE_LOADER_PATH}/include/Geode/Loader.hpp" - "${GEODE_LOADER_PATH}/include/Geode/Utils.hpp" + "${GEODE_LOADER_PATH}/include/Geode/Geode.hpp" # please stop adding modify here its not here because it makes windows compilation take longer than geode 1.0 release date - "${GEODE_LOADER_PATH}/include/Geode/UI.hpp" "${GEODE_LOADER_PATH}/include/Geode/cocos/include/cocos2d.h" "${GEODE_LOADER_PATH}/include/Geode/cocos/extensions/cocos-ext.h" ) diff --git a/codegen/src/AddressGen.cpp b/codegen/src/AddressGen.cpp index 8c3b0bbd..7a81060a 100644 --- a/codegen/src/AddressGen.cpp +++ b/codegen/src/AddressGen.cpp @@ -3,8 +3,13 @@ namespace { namespace format_strings { + char const* address_begin = R"GEN( +#include +)GEN"; + char const* declare_address = R"GEN( -GEODE_INLINE GEODE_HIDDEN static uintptr_t address{index}() {{ +template <> +uintptr_t geode::modifier::address<{index}>() {{ static uintptr_t ret = {address}; return ret; }} @@ -17,6 +22,7 @@ std::string generateAddressHeader(Root& root) { TypeBank bank; bank.loadFrom(root); + output += format_strings::address_begin; for (auto& c : root.classes) { diff --git a/codegen/src/BindingGen.cpp b/codegen/src/BindingGen.cpp index c41d51d4..e53bd7b2 100644 --- a/codegen/src/BindingGen.cpp +++ b/codegen/src/BindingGen.cpp @@ -8,6 +8,7 @@ namespace { namespace format_strings { )GEN"; char const* class_includes = R"GEN(#pragma once +#include #include #include #include diff --git a/codegen/src/Main.cpp b/codegen/src/Main.cpp index 1ab72db0..5a504b37 100644 --- a/codegen/src/Main.cpp +++ b/codegen/src/Main.cpp @@ -31,7 +31,7 @@ int main(int argc, char** argv) try { } } - writeFile(writeDir / "GeneratedAddress.hpp", generateAddressHeader(root)); + writeFile(writeDir / "GeneratedAddress.cpp", generateAddressHeader(root)); writeFile(writeDir / "GeneratedModify.hpp", generateModifyHeader(root, writeDir / "modify")); // writeFile(writeDir / "GeneratedWrapper.hpp", generateWrapperHeader(root)); writeFile(writeDir / "GeneratedType.hpp", generateTypeHeader(root)); diff --git a/codegen/src/ModifyGen.cpp b/codegen/src/ModifyGen.cpp index 12b26e3c..674910da 100644 --- a/codegen/src/ModifyGen.cpp +++ b/codegen/src/ModifyGen.cpp @@ -11,6 +11,7 @@ namespace { #include #include #include +#include {class_include} using namespace geode::modifier; namespace geode::modifier {{ diff --git a/codegen/src/SourceGen.cpp b/codegen/src/SourceGen.cpp index 1120b28e..2d3c39e4 100644 --- a/codegen/src/SourceGen.cpp +++ b/codegen/src/SourceGen.cpp @@ -3,39 +3,64 @@ namespace { namespace format_strings { char const* source_start = R"CAC( +#include #include #include #include #include #include #include +#include +#include +#include using namespace geode; using namespace geode::cast; using cocos2d::CCDestructor; using namespace geode::core::meta; // Default convention using namespace geode::core::meta::x86; // Windows x86 conventions, Function using namespace geode::modifier; // types + +auto wrapFunction(uintptr_t address, tulip::hook::WrapperMetadata const& metadata) { + auto wrapped = tulip::hook::createWrapper(reinterpret_cast(address), metadata); + if (wrapped.isErr()) {{ + log::error("Failed to wrap function {} with error {}", GEODE_PRETTY_FUNCTION, wrapped.unwrapErr()); + throw std::runtime_error(wrapped.unwrapErr()); + }} + return wrapped.unwrap(); +} )CAC"; char const* declare_member = R"GEN( auto {class_name}::{function_name}({parameters}){const} -> decltype({function_name}({arguments})) {{ - auto func = Function({{addresses::address{addr_index}()}}); - return func(this{parameter_comma}{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_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)), + }}); + return reinterpret_cast(func)(this{parameter_comma}{arguments}); }} )GEN"; char const* declare_virtual = R"GEN( auto {class_name}::{function_name}({parameters}){const} -> decltype({function_name}({arguments})) {{ - auto self = addresser::thunkAdjust((types::member{member_index})(&{class_name}::{function_name}), this); - auto func = Function({{addresses::address{addr_index}()}}); - return func(self{parameter_comma}{arguments}); + 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_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)), + }}); + return reinterpret_cast(func)(self{parameter_comma}{arguments}); }} )GEN"; char const* declare_static = R"GEN( auto {class_name}::{function_name}({parameters}){const} -> decltype({function_name}({arguments})) {{ - auto func = Function({{addresses::address{addr_index}()}}); - return func({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_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)), + }}); + return reinterpret_cast(func)({arguments}); }} )GEN"; @@ -44,8 +69,12 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na // basically we destruct it once by calling the gd function, // then lock it, so that other gd destructors dont get called if (CCDestructor::lock(this)) return; - auto func = Function({{addresses::address{addr_index}()}}); - func(this{parameter_comma}{arguments}); + 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_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)), + }}); + reinterpret_cast(func)(this{parameter_comma}{arguments}); // we need to construct it back so that it uhhh ummm doesnt crash // while going to the child destructors auto thing = new (this) {class_name}(std::monostate(), sizeof({class_name})); @@ -60,8 +89,12 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na // no crashes :pray: CCDestructor::lock(this) = true; {class_name}::~{unqualified_class_name}(); - auto func = Function({{addresses::address{addr_index}()}}); - func(this{parameter_comma}{arguments}); + 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_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)), + }}); + reinterpret_cast(func)(this{parameter_comma}{arguments}); }} )GEN"; @@ -149,7 +182,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::getConvention(f)), + fmt::arg("convention", codegen::getModifyConvention(f)), fmt::arg("function_name", fn->beginning.name), fmt::arg("meta_index", ids.meta), fmt::arg("member_index", ids.member), diff --git a/loader/include/Geode/Loader.hpp b/loader/include/Geode/Loader.hpp index 89e17d30..7dee235d 100644 --- a/loader/include/Geode/Loader.hpp +++ b/loader/include/Geode/Loader.hpp @@ -5,7 +5,6 @@ #include "loader/Log.hpp" #include "loader/Mod.hpp" #include "loader/Setting.hpp" -#include "loader/SettingEvent.hpp" #include "loader/Dirs.hpp" #include diff --git a/loader/include/Geode/external/json/json_fwd.hpp b/loader/include/Geode/external/json/json_fwd.hpp new file mode 100644 index 00000000..613e7bce --- /dev/null +++ b/loader/include/Geode/external/json/json_fwd.hpp @@ -0,0 +1,79 @@ +// #include +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ +#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + +#include // int64_t, uint64_t +#include // map +#include // allocator +#include // string +#include // vector + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +namespace nlohmann +{ +/*! +@brief default JSONSerializer template argument + +This serializer ignores the template arguments and uses ADL +([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) +for serialization. +*/ +template +struct adl_serializer; + +template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector> +class basic_json; + +/*! +@brief JSON Pointer + +A JSON pointer defines a string syntax for identifying a specific value +within a JSON document. It can be used with functions `at` and +`operator[]`. Furthermore, JSON pointers are the base for JSON patches. + +@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) + +@since version 2.0.0 +*/ +template +class json_pointer; + +/*! +@brief default JSON class + +This type is the default specialization of the @ref basic_json class which +uses the standard template types. + +@since version 1.0.0 +*/ +using json = basic_json<>; + +template +struct ordered_map; + +/*! +@brief ordered JSON class + +This type preserves the insertion order of object keys. + +@since version 3.9.0 +*/ +using ordered_json = basic_json; + +} // namespace nlohmann + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ \ No newline at end of file diff --git a/loader/include/Geode/loader/Hook.hpp b/loader/include/Geode/loader/Hook.hpp index 6635d798..d1ef0c3c 100644 --- a/loader/include/Geode/loader/Hook.hpp +++ b/loader/include/Geode/loader/Hook.hpp @@ -3,7 +3,7 @@ #include "../DefaultInclude.hpp" #include "../hook-core/Hook.hpp" #include "../utils/general.hpp" -#include "../external/json/json.hpp" +#include "../external/json/json_fwd.hpp" #include #include #include diff --git a/loader/include/Geode/loader/Mod.hpp b/loader/include/Geode/loader/Mod.hpp index d44773ef..86ff9059 100644 --- a/loader/include/Geode/loader/Mod.hpp +++ b/loader/include/Geode/loader/Mod.hpp @@ -2,7 +2,7 @@ #include "../DefaultInclude.hpp" #include "../cocos/support/zip_support/ZipUtils.h" -#include "../external/json/json.hpp" +#include "../external/json/json_fwd.hpp" #include "../utils/Result.hpp" #include "../utils/VersionInfo.hpp" #include "../utils/general.hpp" @@ -111,51 +111,16 @@ namespace geode { nlohmann::json& getSaveContainer(); template - T getSettingValue(std::string const& key) const { - if (auto sett = this->getSetting(key)) { - return SettingValueSetter::get(sett); - } - return T(); - } + T getSettingValue(std::string const& key) const; template - T setSettingValue(std::string const& key, T const& value) { - if (auto sett = this->getSetting(key)) { - auto old = this->getSettingValue(sett); - SettingValueSetter::set(sett, value); - return old; - } - return T(); - } + T setSettingValue(std::string const& key, T const& value); template - T getSavedValue(std::string const& key) { - auto& saved = this->getSaveContainer(); - if (saved.count(key)) { - try { - // json -> T may fail - return saved.at(key); - } - catch (...) { - } - } - return T(); - } + T getSavedValue(std::string const& key); template - T getSavedValue(std::string const& key, T const& defaultValue) { - auto& saved = this->getSaveContainer(); - if (saved.count(key)) { - try { - // json -> T may fail - return saved.at(key); - } - catch (...) { - } - } - saved[key] = defaultValue; - return defaultValue; - } + T getSavedValue(std::string const& key, T const& defaultValue); /** * Set the value of an automatically saved variable. When the game is @@ -165,12 +130,7 @@ namespace geode { * @returns The old value */ template - T setSavedValue(std::string const& key, T const& value) { - auto& saved = this->getSaveContainer(); - auto old = this->getSavedValue(key); - saved[key] = value; - return old; - } + T setSavedValue(std::string const& key, T const& value); /** * Get the mod container stored in the Interface diff --git a/loader/include/Geode/loader/ModInfo.hpp b/loader/include/Geode/loader/ModInfo.hpp index a333f365..9217f918 100644 --- a/loader/include/Geode/loader/ModInfo.hpp +++ b/loader/include/Geode/loader/ModInfo.hpp @@ -1,7 +1,7 @@ #pragma once #include "Types.hpp" -#include "../external/json/json.hpp" +#include "../external/json/json_fwd.hpp" #include "../utils/VersionInfo.hpp" #include "../utils/Result.hpp" #include "Setting.hpp" @@ -157,7 +157,8 @@ namespace geode { static bool validateID(std::string const& id); private: - ModJson m_rawJSON; + // todo: make this a unique_ptr + std::unique_ptr m_rawJSON; /** * Version is passed for backwards diff --git a/loader/include/Geode/loader/ModJsonTest.hpp b/loader/include/Geode/loader/ModJsonTest.hpp new file mode 100644 index 00000000..a6392949 --- /dev/null +++ b/loader/include/Geode/loader/ModJsonTest.hpp @@ -0,0 +1,59 @@ +#include "Mod.hpp" +#include "../external/json/json.hpp" + +namespace geode { + template + T Mod::getSettingValue(std::string const& key) const { + if (auto sett = this->getSetting(key)) { + return SettingValueSetter::get(sett); + } + return T(); + } + + template + T Mod::setSettingValue(std::string const& key, T const& value) { + if (auto sett = this->getSetting(key)) { + auto old = this->getSettingValue(sett); + SettingValueSetter::set(sett, value); + return old; + } + return T(); + } + + template + T Mod::getSavedValue(std::string const& key) { + auto& saved = this->getSaveContainer(); + if (saved.count(key)) { + try { + // json -> T may fail + return saved.at(key); + } + catch (...) { + } + } + return T(); + } + + template + T Mod::getSavedValue(std::string const& key, T const& defaultValue) { + auto& saved = this->getSaveContainer(); + if (saved.count(key)) { + try { + // json -> T may fail + return saved.at(key); + } + catch (...) { + } + } + saved[key] = defaultValue; + return defaultValue; + } + + template + T Mod::setSavedValue(std::string const& key, T const& value) { + auto& saved = this->getSaveContainer(); + auto old = this->getSavedValue(key); + saved[key] = value; + return old; + } +} \ No newline at end of file diff --git a/loader/include/Geode/loader/Setting.hpp b/loader/include/Geode/loader/Setting.hpp index cc1915ba..91ac4c5d 100644 --- a/loader/include/Geode/loader/Setting.hpp +++ b/loader/include/Geode/loader/Setting.hpp @@ -2,10 +2,9 @@ #include "Types.hpp" #include "../DefaultInclude.hpp" -#include "../utils/JsonValidation.hpp" #include "../utils/Result.hpp" #include "../utils/file.hpp" -#include "../external/json/json.hpp" +#include "../external/json/json_fwd.hpp" #include #include @@ -16,6 +15,11 @@ namespace geode { class SettingNode; class SettingValue; + template + struct JsonMaybeObject; + template + struct JsonMaybeValue; + struct GEODE_DLL BoolSetting final { using ValueType = bool; @@ -114,7 +118,8 @@ namespace geode { }; struct GEODE_DLL CustomSetting final { - ModJson json; + // todo: make this an unique_ptr + std::unique_ptr json; }; using SettingKind = std::variant< @@ -190,18 +195,8 @@ namespace geode { m_definition(definition), m_value(definition.defaultValue) {} - bool load(nlohmann::json const& json) override { - try { - m_value = json.get(); - return true; - } catch(...) { - return false; - } - } - bool save(nlohmann::json& json) const { - json = m_value; - return true; - } + bool load(nlohmann::json const& json) override; + bool save(nlohmann::json& json) const; GEODE_DLL SettingNode* createNode(float width) override; T castDefinition() const { diff --git a/loader/include/Geode/loader/SettingJsonTest.hpp b/loader/include/Geode/loader/SettingJsonTest.hpp new file mode 100644 index 00000000..4e162b10 --- /dev/null +++ b/loader/include/Geode/loader/SettingJsonTest.hpp @@ -0,0 +1,21 @@ +#include "Setting.hpp" +#include "../external/json/json.hpp" + +namespace geode { + template + bool GeodeSettingValue::load(nlohmann::json const& json) override { + try { + m_value = json.get(); + return true; + } + catch (...) { + return false; + } + } + + template + bool GeodeSettingValue::save(nlohmann::json& json) const { + json = m_value; + return true; + } +} \ No newline at end of file diff --git a/loader/include/Geode/loader/Types.hpp b/loader/include/Geode/loader/Types.hpp index a3edbbde..956584e5 100644 --- a/loader/include/Geode/loader/Types.hpp +++ b/loader/include/Geode/loader/Types.hpp @@ -2,7 +2,7 @@ #include "../DefaultInclude.hpp" #include "../platform/cplatform.h" -#include "../external/json/json.hpp" +#include "../external/json/json_fwd.hpp" #include diff --git a/loader/include/Geode/modify/Addresses.hpp b/loader/include/Geode/modify/Addresses.hpp index ef8bfee9..41da33b5 100644 --- a/loader/include/Geode/modify/Addresses.hpp +++ b/loader/include/Geode/modify/Addresses.hpp @@ -4,7 +4,6 @@ #include namespace geode::modifier { - struct addresses { -#include - }; + template + uintptr_t address(); } diff --git a/loader/include/Geode/modify/Modify.hpp b/loader/include/Geode/modify/Modify.hpp index d9db0ee6..fac35330 100644 --- a/loader/include/Geode/modify/Modify.hpp +++ b/loader/include/Geode/modify/Modify.hpp @@ -1,6 +1,5 @@ #pragma once #include "../meta/meta.hpp" -#include "Addresses.hpp" #include "AsStaticFunction.hpp" #include "Field.hpp" #include "IDManager.hpp" @@ -18,7 +17,7 @@ if constexpr (Unique::different()) { \ auto hook = Hook::create( \ Mod::get(), \ - reinterpret_cast(addresses::address##AddressIndex_()), \ + reinterpret_cast(address()), \ AsStaticFunction_##FunctionName_::value, \ #ClassName_ "::" #FunctionName_ \ ); \ @@ -32,7 +31,7 @@ constexpr auto d = Resolve<__VA_ARGS__>::func(&Derived::constructor); \ auto hook = Hook::create( \ Mod::get(), \ - reinterpret_cast(addresses::address##AddressIndex_()), \ + reinterpret_cast(address()), \ AsStaticFunction_##constructor::value, \ #ClassName_ "::" #ClassName_ \ ); \ @@ -46,7 +45,7 @@ constexpr auto d = Resolve<>::func(&Derived::destructor); \ auto hook = Hook::create( \ Mod::get(), \ - reinterpret_cast(addresses::address##AddressIndex_()), \ + reinterpret_cast(address()), \ AsStaticFunction_##destructor::value, \ #ClassName_ "::" #ClassName_ \ ); \ diff --git a/loader/include/Geode/modify/Types.hpp b/loader/include/Geode/modify/Types.hpp index cdf15e07..a7b97392 100644 --- a/loader/include/Geode/modify/Types.hpp +++ b/loader/include/Geode/modify/Types.hpp @@ -2,7 +2,7 @@ #include namespace geode::modifier { - struct types { -#include - }; +// struct types { +// #include +// }; } diff --git a/loader/include/Geode/utils/VersionInfo.hpp b/loader/include/Geode/utils/VersionInfo.hpp index 99183860..b21b46e6 100644 --- a/loader/include/Geode/utils/VersionInfo.hpp +++ b/loader/include/Geode/utils/VersionInfo.hpp @@ -2,7 +2,7 @@ #include "../DefaultInclude.hpp" #include -#include "../external/json/json.hpp" +#include "../external/json/json_fwd.hpp" #include #include "../utils/Result.hpp" diff --git a/loader/include/Geode/utils/cocos.hpp b/loader/include/Geode/utils/cocos.hpp index 5f737812..37b95f2a 100644 --- a/loader/include/Geode/utils/cocos.hpp +++ b/loader/include/Geode/utils/cocos.hpp @@ -1,6 +1,6 @@ #pragma once -#include "../external/json/json.hpp" +#include "../external/json/json_fwd.hpp" #include "casts.hpp" #include "general.hpp" #include "../DefaultInclude.hpp" diff --git a/loader/include/Geode/utils/file.hpp b/loader/include/Geode/utils/file.hpp index ef6c5af5..84113f00 100644 --- a/loader/include/Geode/utils/file.hpp +++ b/loader/include/Geode/utils/file.hpp @@ -3,7 +3,7 @@ #include "Result.hpp" #include "general.hpp" -#include "../external/json/json.hpp" +#include "../external/json/json_fwd.hpp" #include #include #include diff --git a/loader/include/Geode/utils/web.hpp b/loader/include/Geode/utils/web.hpp index fcf74efb..ffa20b11 100644 --- a/loader/include/Geode/utils/web.hpp +++ b/loader/include/Geode/utils/web.hpp @@ -1,7 +1,7 @@ #pragma once #include "../DefaultInclude.hpp" -#include "../external/json/json.hpp" +#include "../external/json/json_fwd.hpp" #include "Result.hpp" #include "general.hpp" @@ -46,17 +46,7 @@ namespace geode::utils::web { * @param url URL to fetch * @returns Returned data as JSON, or error on error */ - template - Result fetchJSON(std::string const& url) { - std::string res; - GEODE_UNWRAP_INTO(res, fetch(url)); - try { - return Ok(Json::parse(res)); - } - catch (std::exception& e) { - return Err(e.what()); - } - } + Result fetchJSON(std::string const& url); class SentAsyncWebRequest; template diff --git a/loader/src/loader/Setting.cpp b/loader/src/loader/Setting.cpp index 7d813206..e8a4687d 100644 --- a/loader/src/loader/Setting.cpp +++ b/loader/src/loader/Setting.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include USE_GEODE_NAMESPACE(); diff --git a/loader/src/utils/web.cpp b/loader/src/utils/web.cpp index 32681852..6397a95a 100644 --- a/loader/src/utils/web.cpp +++ b/loader/src/utils/web.cpp @@ -97,6 +97,17 @@ Result web::fetchBytes(std::string const& url) { return Err("Error getting info: " + std::string(curl_easy_strerror(res))); } +Result web::fetchJSON(std::string const& url) { + std::string res; + GEODE_UNWRAP_INTO(res, fetch(url)); + try { + return Ok(nlohmann::json::parse(res)); + } + catch (std::exception& e) { + return Err(e.what()); + } +} + Result web::fetch(std::string const& url) { auto curl = curl_easy_init(); From dc0da9fc56baf5bdd4afbd252f225a98e0002fdd Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Jan 2023 02:00:59 +0300 Subject: [PATCH 16/31] make it compile on macos --- CMakeLists.txt | 19 ++++++++++--- codegen/src/AddressGen.cpp | 1 + codegen/src/SourceGen.cpp | 28 ++++++++++++------- loader/include/Geode/cocos/cocoa/CCObject.h | 18 +++--------- loader/include/Geode/loader/IPC.hpp | 11 ++------ loader/include/Geode/loader/ModInfo.hpp | 3 +- loader/include/Geode/loader/Setting.hpp | 3 +- .../include/Geode/loader/SettingJsonTest.hpp | 2 +- loader/include/Geode/modify/Addresses.hpp | 3 -- loader/include/Geode/modify/Modify.hpp | 1 - loader/src/loader/IPC.cpp | 8 ++++++ loader/src/loader/Index.cpp | 2 ++ loader/src/loader/LoaderImpl.cpp | 1 + loader/src/loader/ModImpl.cpp | 1 + loader/src/loader/ModImpl.hpp | 2 ++ loader/src/loader/ModInfo.cpp | 12 ++++---- loader/src/loader/Patch.cpp | 2 +- loader/src/loader/Setting.cpp | 3 +- loader/src/main.cpp | 4 ++- loader/src/utils/VersionInfo.cpp | 1 + loader/src/utils/cocos.cpp | 1 + loader/src/utils/file.cpp | 1 + loader/src/utils/web.cpp | 1 + loader/test/dependency/main.cpp | 2 ++ loader/test/main/main.cpp | 1 + 25 files changed, 78 insertions(+), 53 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d36e983b..641e3af3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,20 @@ if (NOT EXISTS ${GEODE_CODEGEN_PATH}/Geode/GeneratedAddress.cpp) file(TOUCH ${GEODE_CODEGEN_PATH}/Geode/GeneratedAddress.cpp) endif() -target_sources(${PROJECT_NAME} INTERFACE ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp ${GEODE_CODEGEN_PATH}/Geode/GeneratedAddress.cpp) +add_library(GeodeCodegenSources ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp ${GEODE_CODEGEN_PATH}/Geode/GeneratedAddress.cpp) +target_link_directories(GeodeCodegenSources PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/loader/include/link) +target_link_libraries(GeodeCodegenSources PRIVATE ghc_filesystem fmt TulipHookInclude) +target_include_directories(GeodeCodegenSources PRIVATE + ${GEODE_CODEGEN_PATH} + ${GEODE_LOADER_PATH}/include + ${GEODE_LOADER_PATH}/include/Geode/cocos/include + ${GEODE_LOADER_PATH}/include/Geode/cocos/extensions + ${GEODE_LOADER_PATH}/include/Geode/fmod +) +target_compile_features(GeodeCodegenSources PUBLIC cxx_std_20) +target_precompile_headers(GeodeCodegenSources INTERFACE + "${GEODE_LOADER_PATH}/include/Geode/Bindings.hpp" +) target_include_directories(${PROJECT_NAME} INTERFACE ${GEODE_CODEGEN_PATH} @@ -112,7 +125,7 @@ CPMAddPackage("gh:gulrak/filesystem#3e5b930") # Tulip hook (hooking) CPMAddPackage("gh:altalk23/TulipHook#298d572") -target_link_libraries(${PROJECT_NAME} INTERFACE ghc_filesystem fmt TulipHookInclude) +target_link_libraries(${PROJECT_NAME} INTERFACE ghc_filesystem fmt TulipHookInclude GeodeCodegenSources) if (NOT EXISTS ${GEODE_BIN_PATH}) @@ -139,8 +152,6 @@ elseif(EXISTS ${GEODE_PLATFORM_BIN_PATH}) "${GEODE_LOADER_PATH}/include/Geode/DefaultInclude.hpp" "${GEODE_LOADER_PATH}/include/Geode/Geode.hpp" # please stop adding modify here its not here because it makes windows compilation take longer than geode 1.0 release date - "${GEODE_LOADER_PATH}/include/Geode/cocos/include/cocos2d.h" - "${GEODE_LOADER_PATH}/include/Geode/cocos/extensions/cocos-ext.h" ) else() message(FATAL_ERROR diff --git a/codegen/src/AddressGen.cpp b/codegen/src/AddressGen.cpp index 7a81060a..969c8673 100644 --- a/codegen/src/AddressGen.cpp +++ b/codegen/src/AddressGen.cpp @@ -4,6 +4,7 @@ namespace { namespace format_strings { char const* address_begin = R"GEN( +#include #include )GEN"; diff --git a/codegen/src/SourceGen.cpp b/codegen/src/SourceGen.cpp index 2d3c39e4..9ed4089d 100644 --- a/codegen/src/SourceGen.cpp +++ b/codegen/src/SourceGen.cpp @@ -6,24 +6,32 @@ namespace { namespace format_strings { #include #include #include -#include -#include -#include -#include +#include #include #include -#include + using namespace geode; -using namespace geode::cast; +using namespace geode::modifier; using cocos2d::CCDestructor; -using namespace geode::core::meta; // Default convention -using namespace geode::core::meta::x86; // Windows x86 conventions, Function -using namespace geode::modifier; // types + +std::unordered_map& CCDestructor::destructorLock() {{ + static auto ret = new std::unordered_map; + return *ret; +}} +bool& CCDestructor::globalLock() {{ + static thread_local bool ret = false; + return ret; +}} +bool& CCDestructor::lock(void* self) { + return destructorLock()[self]; +} +CCDestructor::~CCDestructor() {{ + destructorLock().erase(this); +}} auto wrapFunction(uintptr_t address, tulip::hook::WrapperMetadata const& metadata) { auto wrapped = tulip::hook::createWrapper(reinterpret_cast(address), metadata); if (wrapped.isErr()) {{ - log::error("Failed to wrap function {} with error {}", GEODE_PRETTY_FUNCTION, wrapped.unwrapErr()); throw std::runtime_error(wrapped.unwrapErr()); }} return wrapped.unwrap(); diff --git a/loader/include/Geode/cocos/cocoa/CCObject.h b/loader/include/Geode/cocos/cocoa/CCObject.h index e6bd1135..1f7adfae 100644 --- a/loader/include/Geode/cocos/cocoa/CCObject.h +++ b/loader/include/Geode/cocos/cocoa/CCObject.h @@ -79,21 +79,11 @@ public: */ class CCDestructor : public CCCopying { private: - static inline auto& destructorLock() { - static auto ret = new std::unordered_map; - return *ret; - } + static std::unordered_map& destructorLock(); public: - static inline bool& globalLock() { - static thread_local bool ret = false; - return ret; - } - static inline bool& lock(void* self) { - return destructorLock()[self]; - } - inline ~CCDestructor() { - destructorLock().erase(this); - } + static bool& globalLock(); + static bool& lock(void* self); + ~CCDestructor(); }; #pragma warning(push) diff --git a/loader/include/Geode/loader/IPC.hpp b/loader/include/Geode/loader/IPC.hpp index 594ee043..5d818bf6 100644 --- a/loader/include/Geode/loader/IPC.hpp +++ b/loader/include/Geode/loader/IPC.hpp @@ -2,6 +2,7 @@ #include "Event.hpp" #include "Loader.hpp" +#include "../external/json/json_fwd.hpp" namespace geode { #ifdef GEODE_IS_WINDOWS @@ -31,7 +32,7 @@ namespace geode { public: std::string targetModID; std::string messageID; - nlohmann::json messageData; + std::unique_ptr messageData; nlohmann::json& replyData; friend class IPCFilter; @@ -62,11 +63,5 @@ namespace geode { ); }; - template - std::monostate listenForIPC(std::string const& messageID, nlohmann::json(*callback)(IPCEvent*)) { - (void) new EventListener( - callback, IPCFilter(getMod()->getID(), messageID) - ); - return std::monostate(); - } + std::monostate listenForIPC(std::string const& messageID, nlohmann::json(*callback)(IPCEvent*)); } diff --git a/loader/include/Geode/loader/ModInfo.hpp b/loader/include/Geode/loader/ModInfo.hpp index 9217f918..058c42ef 100644 --- a/loader/include/Geode/loader/ModInfo.hpp +++ b/loader/include/Geode/loader/ModInfo.hpp @@ -157,8 +157,7 @@ namespace geode { static bool validateID(std::string const& id); private: - // todo: make this a unique_ptr - std::unique_ptr m_rawJSON; + std::shared_ptr m_rawJSON; /** * Version is passed for backwards diff --git a/loader/include/Geode/loader/Setting.hpp b/loader/include/Geode/loader/Setting.hpp index 91ac4c5d..a46b9bc5 100644 --- a/loader/include/Geode/loader/Setting.hpp +++ b/loader/include/Geode/loader/Setting.hpp @@ -118,8 +118,7 @@ namespace geode { }; struct GEODE_DLL CustomSetting final { - // todo: make this an unique_ptr - std::unique_ptr json; + std::shared_ptr json; }; using SettingKind = std::variant< diff --git a/loader/include/Geode/loader/SettingJsonTest.hpp b/loader/include/Geode/loader/SettingJsonTest.hpp index 4e162b10..50b12b20 100644 --- a/loader/include/Geode/loader/SettingJsonTest.hpp +++ b/loader/include/Geode/loader/SettingJsonTest.hpp @@ -3,7 +3,7 @@ namespace geode { template - bool GeodeSettingValue::load(nlohmann::json const& json) override { + bool GeodeSettingValue::load(nlohmann::json const& json) { try { m_value = json.get(); return true; diff --git a/loader/include/Geode/modify/Addresses.hpp b/loader/include/Geode/modify/Addresses.hpp index 41da33b5..7f342e47 100644 --- a/loader/include/Geode/modify/Addresses.hpp +++ b/loader/include/Geode/modify/Addresses.hpp @@ -1,7 +1,4 @@ #pragma once -#include "Types.hpp" - -#include namespace geode::modifier { template diff --git a/loader/include/Geode/modify/Modify.hpp b/loader/include/Geode/modify/Modify.hpp index fac35330..e3c43571 100644 --- a/loader/include/Geode/modify/Modify.hpp +++ b/loader/include/Geode/modify/Modify.hpp @@ -3,7 +3,6 @@ #include "AsStaticFunction.hpp" #include "Field.hpp" #include "IDManager.hpp" -#include "Types.hpp" #include #include diff --git a/loader/src/loader/IPC.cpp b/loader/src/loader/IPC.cpp index dafb4e80..f882b477 100644 --- a/loader/src/loader/IPC.cpp +++ b/loader/src/loader/IPC.cpp @@ -1,7 +1,15 @@ #include +#include USE_GEODE_NAMESPACE(); +std::monostate geode::listenForIPC(std::string const& messageID, nlohmann::json(*callback)(IPCEvent*)) { + (void) new EventListener( + callback, IPCFilter(getMod()->getID(), messageID) + ); + return std::monostate(); +} + IPCEvent::IPCEvent( void* rawPipeHandle, std::string const& targetModID, diff --git a/loader/src/loader/Index.cpp b/loader/src/loader/Index.cpp index cbfa4916..9b95ef94 100644 --- a/loader/src/loader/Index.cpp +++ b/loader/src/loader/Index.cpp @@ -6,6 +6,8 @@ #include #include #include +#include + USE_GEODE_NAMESPACE(); diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index bde9cc8d..6e46dc8c 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index a663eb41..aac9a1d9 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/loader/src/loader/ModImpl.hpp b/loader/src/loader/ModImpl.hpp index 2d38d027..29437433 100644 --- a/loader/src/loader/ModImpl.hpp +++ b/loader/src/loader/ModImpl.hpp @@ -1,5 +1,7 @@ #pragma once +#include + namespace geode { class Mod::Impl { public: diff --git a/loader/src/loader/ModInfo.cpp b/loader/src/loader/ModInfo.cpp index 644d1789..0da345e1 100644 --- a/loader/src/loader/ModInfo.cpp +++ b/loader/src/loader/ModInfo.cpp @@ -2,6 +2,9 @@ #include #include #include +#include +#include + #include USE_GEODE_NAMESPACE(); @@ -36,10 +39,9 @@ bool ModInfo::validateID(std::string const& id) { Result ModInfo::createFromSchemaV010(ModJson const& rawJson) { ModInfo info; - auto json = rawJson; - info.m_rawJSON = rawJson; + info.m_rawJSON = std::make_unique(rawJson); - JsonChecker checker(json); + JsonChecker checker(*info.m_rawJSON); auto root = checker.root("[mod.json]").obj(); root.addKnownKey("geode"); @@ -242,14 +244,14 @@ std::vector*>> ModInfo::getSpe } ModJson ModInfo::toJSON() const { - auto json = m_rawJSON; + auto json = *m_rawJSON; json["path"] = this->path; json["binary"] = this->binaryName; return json; } ModJson ModInfo::getRawJSON() const { - return m_rawJSON; + return *m_rawJSON; } bool ModInfo::operator==(ModInfo const& other) const { diff --git a/loader/src/loader/Patch.cpp b/loader/src/loader/Patch.cpp index 8ff91e7e..9c0e4aa0 100644 --- a/loader/src/loader/Patch.cpp +++ b/loader/src/loader/Patch.cpp @@ -1,5 +1,5 @@ #include -// #include +#include USE_GEODE_NAMESPACE(); diff --git a/loader/src/loader/Setting.cpp b/loader/src/loader/Setting.cpp index e8a4687d..06019a09 100644 --- a/loader/src/loader/Setting.cpp +++ b/loader/src/loader/Setting.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -132,7 +133,7 @@ Result Setting::parse( case hash("custom"): { sett.m_kind = CustomSetting { - .json = obj.json() + .json = std::make_shared(obj.json()) }; // skip checking unknown keys return Ok(sett); diff --git a/loader/src/main.cpp b/loader/src/main.cpp index aefc2889..dc7fb615 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include USE_GEODE_NAMESPACE(); @@ -127,7 +129,7 @@ $execute { listenForIPC("list-mods", [](IPCEvent* event) -> nlohmann::json { std::vector res; - auto args = event->messageData; + auto args = *event->messageData; JsonChecker checker(args); auto root = checker.root("").obj(); diff --git a/loader/src/utils/VersionInfo.cpp b/loader/src/utils/VersionInfo.cpp index c564a737..202ecd02 100644 --- a/loader/src/utils/VersionInfo.cpp +++ b/loader/src/utils/VersionInfo.cpp @@ -4,6 +4,7 @@ #include #include +#include USE_GEODE_NAMESPACE(); diff --git a/loader/src/utils/cocos.cpp b/loader/src/utils/cocos.cpp index 7f79ef30..0f30080c 100644 --- a/loader/src/utils/cocos.cpp +++ b/loader/src/utils/cocos.cpp @@ -1,5 +1,6 @@ #include #include +#include USE_GEODE_NAMESPACE(); diff --git a/loader/src/utils/file.cpp b/loader/src/utils/file.cpp index 9734e530..95c74343 100644 --- a/loader/src/utils/file.cpp +++ b/loader/src/utils/file.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include USE_GEODE_NAMESPACE(); diff --git a/loader/src/utils/web.cpp b/loader/src/utils/web.cpp index 6397a95a..26c6b1f6 100644 --- a/loader/src/utils/web.cpp +++ b/loader/src/utils/web.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include USE_GEODE_NAMESPACE(); diff --git a/loader/test/dependency/main.cpp b/loader/test/dependency/main.cpp index 1c407338..ae2df000 100644 --- a/loader/test/dependency/main.cpp +++ b/loader/test/dependency/main.cpp @@ -4,6 +4,8 @@ USE_GEODE_NAMESPACE(); #include #include +#include + enum class Icon { Steve, diff --git a/loader/test/main/main.cpp b/loader/test/main/main.cpp index e5a2c31d..0da97db7 100644 --- a/loader/test/main/main.cpp +++ b/loader/test/main/main.cpp @@ -1,4 +1,5 @@ #include +#include USE_GEODE_NAMESPACE(); From d093efbc8b72ebfd995aaf5092a7d79dc1da22b3 Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Thu, 19 Jan 2023 21:58:22 -0300 Subject: [PATCH 17/31] fix codegen issues --- CMakeLists.txt | 2 +- codegen/src/AddressGen.cpp | 5 +++-- codegen/src/BindingGen.cpp | 1 + loader/include/Geode/cocos/platform/CCPlatformMacros.h | 9 ++++++++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 641e3af3..7acaed9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,7 +123,7 @@ CPMAddPackage("gh:fmtlib/fmt#9.1.0") CPMAddPackage("gh:gulrak/filesystem#3e5b930") # Tulip hook (hooking) -CPMAddPackage("gh:altalk23/TulipHook#298d572") +CPMAddPackage("gh:geode-sdk/TulipHook#fd27e4a") target_link_libraries(${PROJECT_NAME} INTERFACE ghc_filesystem fmt TulipHookInclude GeodeCodegenSources) diff --git a/codegen/src/AddressGen.cpp b/codegen/src/AddressGen.cpp index 969c8673..4921ab8e 100644 --- a/codegen/src/AddressGen.cpp +++ b/codegen/src/AddressGen.cpp @@ -6,6 +6,7 @@ namespace { namespace format_strings { char const* address_begin = R"GEN( #include #include +#include )GEN"; char const* declare_address = R"GEN( @@ -39,9 +40,9 @@ std::string generateAddressHeader(Root& root) { if (codegen::getStatus(field) == BindStatus::Binded) { const auto ids = bank.getIDs(fn->beginning, c.name); - address_str = fmt::format("addresser::get{}Virtual((types::member{})(&{}::{}))", + address_str = fmt::format("addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))", str_if("Non", !fn->beginning.is_virtual), - ids.member, + codegen::getParameterTypes(fn->beginning), field.parent, fn->beginning.name ); diff --git a/codegen/src/BindingGen.cpp b/codegen/src/BindingGen.cpp index e53bd7b2..8ae7f092 100644 --- a/codegen/src/BindingGen.cpp +++ b/codegen/src/BindingGen.cpp @@ -21,6 +21,7 @@ namespace { namespace format_strings { char const* class_no_includes = R"GEN(#pragma once #include +#include )GEN"; diff --git a/loader/include/Geode/cocos/platform/CCPlatformMacros.h b/loader/include/Geode/cocos/platform/CCPlatformMacros.h index fa0885bc..9ae219b9 100644 --- a/loader/include/Geode/cocos/platform/CCPlatformMacros.h +++ b/loader/include/Geode/cocos/platform/CCPlatformMacros.h @@ -114,6 +114,8 @@ It's new in cocos2d-x since v0.99.5 */ class GeodeNodeMetadata; +#include + namespace geode { struct modify; @@ -123,6 +125,9 @@ namespace geode { template class ModifyDerive; + + template + uintptr_t address(); } } @@ -131,7 +136,9 @@ namespace geode { template \ friend class ::geode::modifier::ModifyDerive; \ friend struct ::geode::modifier::types; \ - friend class ::GeodeNodeMetadata; + friend class ::GeodeNodeMetadata; \ + template \ + friend uintptr_t geode::modifier::address(); #define GEODE_ADD(...) __VA_ARGS__ #ifdef __cplusplus From 1b8123c99717f95da42d2e946ec0a0ca3f8b012d Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Thu, 19 Jan 2023 22:20:43 -0300 Subject: [PATCH 18/31] fix ColorPickerDelegate --- .../extensions/GUI/CCControlExtension/ColorPickerDelegate.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/ColorPickerDelegate.h b/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/ColorPickerDelegate.h index 98e78df9..63823c09 100644 --- a/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/ColorPickerDelegate.h +++ b/loader/include/Geode/cocos/extensions/GUI/CCControlExtension/ColorPickerDelegate.h @@ -44,7 +44,8 @@ NS_CC_EXT_BEGIN * @{ */ -class GEODE_DLL ColorPickerDelegate { +class CC_DLL ColorPickerDelegate { +public: virtual void colorValueChanged(ccColor3B) {} }; From f089afc27cacde1a541bf7df07b7b2d146d0d44a Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Sat, 21 Jan 2023 16:00:14 +0200 Subject: [PATCH 19/31] fix includes + add some doccing --- entry.cpp | 2 +- loader/include/Geode/Loader.hpp | 1 + loader/include/Geode/loader/Hook.hpp | 41 ++++++++++++++++++++++++++-- loader/src/loader/Hook.cpp | 13 +++++++-- loader/src/loader/HookImpl.hpp | 9 +++++- loader/src/loader/ModImpl.cpp | 1 + loader/test/main/main.cpp | 1 + 7 files changed, 61 insertions(+), 7 deletions(-) diff --git a/entry.cpp b/entry.cpp index cd4cc17d..937e32ca 100644 --- a/entry.cpp +++ b/entry.cpp @@ -16,4 +16,4 @@ namespace geode { namespace { // to make sure the instance is set into the sharedMod<> in load time static auto mod = geode::getMod(); -} \ No newline at end of file +} diff --git a/loader/include/Geode/Loader.hpp b/loader/include/Geode/Loader.hpp index 7dee235d..a1bb4c37 100644 --- a/loader/include/Geode/Loader.hpp +++ b/loader/include/Geode/Loader.hpp @@ -4,6 +4,7 @@ #include "loader/Loader.hpp" #include "loader/Log.hpp" #include "loader/Mod.hpp" +#include "loader/ModEvent.hpp" #include "loader/Setting.hpp" #include "loader/Dirs.hpp" diff --git a/loader/include/Geode/loader/Hook.hpp b/loader/include/Geode/loader/Hook.hpp index d1ef0c3c..c3e89a80 100644 --- a/loader/include/Geode/loader/Hook.hpp +++ b/loader/include/Geode/loader/Hook.hpp @@ -26,15 +26,50 @@ namespace geode { Result<> disable(); public: - static Hook* create(Mod* owner, void* address, void* detour, std::string const& displayName, tulip::hook::HandlerMetadata const& handlerMetadata, tulip::hook::HookMetadata const& hookMetadata); + /** + * Create a hook at an address. The hook is enabled immediately. By + * default, the hook is placed at the end of the detour list; however, + * this can be controlled using metadata settings. + * @param owner The mod that owns this hook; must be provided + * @param address The address to hook + * @param detour The detour to run when the hook is hit. The detour's + * calling convention should be cdecl + * @param displayName A human-readable name describing the hook, + * usually the fully qualified name of the function being hooked + * @param handlerMetadata Metadata for the hook handler + * @param hookMetadata Metadata for the hook itself + * @returns The created hook, or an error. Make sure to add the created + * hook to the mod that owns it using mod->addHook! + */ + static Hook* create( + Mod* owner, + void* address, + void* detour, + std::string const& displayName, + tulip::hook::HandlerMetadata const& handlerMetadata, + tulip::hook::HookMetadata const& hookMetadata + ); template - static Hook* create(Mod* owner, void* address, DetourType detour, std::string const& displayName, tulip::hook::HookMetadata const& hookMetadata = tulip::hook::HookMetadata()) { + static Hook* create( + Mod* owner, + void* address, + DetourType detour, + std::string const& displayName, + tulip::hook::HookMetadata const& hookMetadata = tulip::hook::HookMetadata() + ) { auto handlerMetadata = tulip::hook::HandlerMetadata{ .m_convention = std::make_shared(), .m_abstract = tulip::hook::AbstractFunction::from(detour) }; - return Hook::create(owner, address, reinterpret_cast(detour), displayName, handlerMetadata, hookMetadata); + return Hook::create( + owner, + address, + reinterpret_cast(detour), + displayName, + handlerMetadata, + hookMetadata + ); } Hook(Hook const&) = delete; diff --git a/loader/src/loader/Hook.cpp b/loader/src/loader/Hook.cpp index ee1d5a9b..f3125191 100644 --- a/loader/src/loader/Hook.cpp +++ b/loader/src/loader/Hook.cpp @@ -15,8 +15,17 @@ USE_GEODE_NAMESPACE(); Hook::Hook(std::shared_ptr&& impl) : m_impl(std::move(impl)) {} Hook::~Hook() {} -Hook* Hook::create(Mod* owner, void* address, void* detour, std::string const& displayName, tulip::hook::HandlerMetadata const& handlerMetadata, tulip::hook::HookMetadata const& hookMetadata) { - auto impl = std::make_shared(address, detour, displayName, handlerMetadata, hookMetadata, owner); +Hook* Hook::create( + Mod* owner, + void* address, + void* detour, + std::string const& displayName, + tulip::hook::HandlerMetadata const& handlerMetadata, + tulip::hook::HookMetadata const& hookMetadata +) { + auto impl = std::make_shared( + address, detour, displayName, handlerMetadata, hookMetadata, owner + ); return new Hook(std::move(impl)); } diff --git a/loader/src/loader/HookImpl.hpp b/loader/src/loader/HookImpl.hpp index 5cd891c9..551f38d5 100644 --- a/loader/src/loader/HookImpl.hpp +++ b/loader/src/loader/HookImpl.hpp @@ -13,7 +13,14 @@ USE_GEODE_NAMESPACE(); class Hook::Impl { public: - Impl(void* address, void* detour, std::string const& displayName, tulip::hook::HandlerMetadata const& handlerMetadata, tulip::hook::HookMetadata const& hookMetadata, Mod* owner); + Impl( + void* address, + void* detour, + std::string const& displayName, + tulip::hook::HandlerMetadata const& handlerMetadata, + tulip::hook::HookMetadata const& hookMetadata, + Mod* owner + ); ~Impl(); diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index aac9a1d9..37da6a7a 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/loader/test/main/main.cpp b/loader/test/main/main.cpp index 0da97db7..a94d3001 100644 --- a/loader/test/main/main.cpp +++ b/loader/test/main/main.cpp @@ -1,5 +1,6 @@ #include #include +#include USE_GEODE_NAMESPACE(); From 51f70bc8107421ebf44c00cdf556c60c8f45083c Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Sat, 21 Jan 2023 16:42:39 +0200 Subject: [PATCH 20/31] fix getMod being undefined because silly me marked it inline --- entry.cpp | 1 + loader/include/Geode/loader/ModEvent.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/entry.cpp b/entry.cpp index 937e32ca..cf19cb70 100644 --- a/entry.cpp +++ b/entry.cpp @@ -1,3 +1,4 @@ + #include #include diff --git a/loader/include/Geode/loader/ModEvent.hpp b/loader/include/Geode/loader/ModEvent.hpp index 496a66e8..15c63d7c 100644 --- a/loader/include/Geode/loader/ModEvent.hpp +++ b/loader/include/Geode/loader/ModEvent.hpp @@ -6,7 +6,7 @@ namespace geode { class Mod; - inline Mod* getMod(); + Mod* getMod(); enum class ModEventType { Loaded, From d8c0ba6799d3279eeb8a9c5f67844caa36797777 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 21 Jan 2023 19:54:19 +0300 Subject: [PATCH 21/31] fix internal mod setting up at static init time --- bindings/GeometryDash.bro | 1 + loader/src/loader/LoaderImpl.cpp | 7 ++++--- loader/src/loader/LoaderImpl.hpp | 1 + loader/src/loader/ModImpl.cpp | 9 ++++++--- loader/src/main.cpp | 11 +++++++++++ 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index d63b6b95..284703a5 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -3799,6 +3799,7 @@ class LevelSettingsObject : cocos2d::CCNode { int m_groundIndex; int m_fontIndex; bool m_startsWithStartPos; + bool m_isFlipped; GJGameLevel* m_level; gd::string m_guidelineString; int m_unknown; diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index 6e46dc8c..ddb5604b 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -591,13 +591,14 @@ ResourceDownloadFilter::ResourceDownloadFilter() {} void Loader::Impl::provideNextMod(Mod* mod) { m_nextModLock.lock(); - m_nextMod = mod; + if (mod) { + m_nextMod = mod; + } } Mod* Loader::Impl::takeNextMod() { if (!m_nextMod) { - this->setupInternalMod(); - m_nextMod = Mod::sharedMod<>; + m_nextMod = this->createInternalMod(); } auto ret = m_nextMod; return ret; diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp index ee715655..c96853db 100644 --- a/loader/src/loader/LoaderImpl.hpp +++ b/loader/src/loader/LoaderImpl.hpp @@ -134,6 +134,7 @@ namespace geode { bool isReadyToHook() const; void addInternalHook(Hook* hook, Mod* mod); + Mod* createInternalMod(); void setupInternalMod(); }; diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index 37da6a7a..38f33736 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -669,12 +669,15 @@ static ModInfo getModImplInfo() { } } -void Loader::Impl::setupInternalMod() { +Mod* Loader::Impl::createInternalMod() { auto& mod = Mod::sharedMod<>; - if (mod) return; + if (mod) return mod; mod = new Mod(getModImplInfo()); + return mod; +} - auto setupRes = mod->m_impl->setup(); +void Loader::Impl::setupInternalMod() { + auto setupRes = Mod::get()->m_impl->setup(); if (!setupRes) { log::error("Failed to setup internal mod! ({})", setupRes.unwrapErr()); } diff --git a/loader/src/main.cpp b/loader/src/main.cpp index dc7fb615..f7a6d176 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -164,6 +164,17 @@ int geodeEntry(void* platformData) { return 1; } + // set up internal mod, settings and data + if (!LoaderImpl::get()->setup()) { + LoaderImpl::get()->setupInternalMod( + "Unable to Load Geode!", + "There was an unknown fatal error setting up " + "the internal mod and Geode can not be loaded." + ); + LoaderImpl::get()->reset(); + return 1; + } + // set up loader, load mods, etc. auto setupRes = LoaderImpl::get()->setup(); if (!setupRes) { From 394cb967330c020be09c0a1b5783727763e9467e Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 21 Jan 2023 19:56:01 +0300 Subject: [PATCH 22/31] fix silly entry --- loader/src/main.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/loader/src/main.cpp b/loader/src/main.cpp index f7a6d176..e4ce0ea5 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -165,8 +165,8 @@ int geodeEntry(void* platformData) { } // set up internal mod, settings and data - if (!LoaderImpl::get()->setup()) { - LoaderImpl::get()->setupInternalMod( + if (!LoaderImpl::get()->setupInternalMod()) { + LoaderImpl::get()->platformMessageBox( "Unable to Load Geode!", "There was an unknown fatal error setting up " "the internal mod and Geode can not be loaded." @@ -176,8 +176,7 @@ int geodeEntry(void* platformData) { } // set up loader, load mods, etc. - auto setupRes = LoaderImpl::get()->setup(); - if (!setupRes) { + if (!LoaderImpl::get()->setup()) { LoaderImpl::get()->platformMessageBox( "Unable to Load Geode!", "There was an unknown fatal error setting up " From e322cc5fae8b2f5f6fddc1fc98e920e777ad8b6e Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Sat, 21 Jan 2023 19:02:23 +0200 Subject: [PATCH 23/31] fix internal mod being setup at static init time --- loader/include/Geode/loader/Mod.hpp | 5 ++--- loader/src/loader/ModImpl.cpp | 10 +++------- loader/src/main.cpp | 12 ++++++++++++ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/loader/include/Geode/loader/Mod.hpp b/loader/include/Geode/loader/Mod.hpp index 7afd8f8f..6fba9337 100644 --- a/loader/include/Geode/loader/Mod.hpp +++ b/loader/include/Geode/loader/Mod.hpp @@ -133,9 +133,8 @@ namespace geode { T setSavedValue(std::string const& key, T const& value); /** - * Get the mod container stored in the Interface - * @returns nullptr if Interface is not initialized, - * the mod pointer if it is initialized + * Get the Mod of the current mod being developed + * @returns The current mod */ template static inline GEODE_HIDDEN Mod* get() { diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index 37da6a7a..dc639339 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -21,8 +21,6 @@ Mod::Impl* ModImpl::getImpl(Mod* mod) { } Mod::Impl::Impl(Mod* self, ModInfo const& info) : m_self(self), m_info(info) { - m_saveDirPath = dirs::getModsSaveDir() / info.id; - ghc::filesystem::create_directories(m_saveDirPath); } Mod::Impl::~Impl() { @@ -30,6 +28,9 @@ Mod::Impl::~Impl() { } Result<> Mod::Impl::setup() { + m_saveDirPath = dirs::getModsSaveDir() / m_info.id; + ghc::filesystem::create_directories(m_saveDirPath); + this->setupSettings(); auto loadRes = this->loadData(); if (!loadRes) { @@ -673,9 +674,4 @@ void Loader::Impl::setupInternalMod() { auto& mod = Mod::sharedMod<>; if (mod) return; mod = new Mod(getModImplInfo()); - - auto setupRes = mod->m_impl->setup(); - if (!setupRes) { - log::error("Failed to setup internal mod! ({})", setupRes.unwrapErr()); - } } \ No newline at end of file diff --git a/loader/src/main.cpp b/loader/src/main.cpp index dc7fb615..7babfc83 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -154,6 +154,18 @@ $execute { int geodeEntry(void* platformData) { // setup internals + auto intModSetupRes = ModImpl::getImpl(Mod::get())->setup(); + if (!intModSetupRes) { + LoaderImpl::get()->platformMessageBox( + "Unable to load Geode!", + "There was an unknown fatal error setting up " + "the internal mod representation and Geode can " + "not be loaded. " + "(" + intModSetupRes.unwrapErr() + ")" + ); + return 1; + } + if (!geode::core::hook::initialize()) { LoaderImpl::get()->platformMessageBox( "Unable to load Geode!", From c72967abb55cb136bd632fa64b04b00e6270259f Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 21 Jan 2023 23:07:58 +0300 Subject: [PATCH 24/31] fix setup compilation errors --- loader/src/loader/LoaderImpl.hpp | 2 +- loader/src/loader/ModImpl.cpp | 7 ++----- loader/src/main.cpp | 8 +++++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp index c96853db..e0527fbe 100644 --- a/loader/src/loader/LoaderImpl.hpp +++ b/loader/src/loader/LoaderImpl.hpp @@ -135,7 +135,7 @@ namespace geode { void addInternalHook(Hook* hook, Mod* mod); Mod* createInternalMod(); - void setupInternalMod(); + Result<> setupInternalMod(); }; class LoaderImpl { diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index 38f33736..82c15ea5 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -676,9 +676,6 @@ Mod* Loader::Impl::createInternalMod() { return mod; } -void Loader::Impl::setupInternalMod() { - auto setupRes = Mod::get()->m_impl->setup(); - if (!setupRes) { - log::error("Failed to setup internal mod! ({})", setupRes.unwrapErr()); - } +Result<> Loader::Impl::setupInternalMod() { + return Mod::get()->m_impl->setup(); } \ No newline at end of file diff --git a/loader/src/main.cpp b/loader/src/main.cpp index e4ce0ea5..93f87411 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -165,18 +165,20 @@ int geodeEntry(void* platformData) { } // set up internal mod, settings and data - if (!LoaderImpl::get()->setupInternalMod()) { + auto internalSetupRes = LoaderImpl::get()->setupInternalMod(); + if (!internalSetupRes) { LoaderImpl::get()->platformMessageBox( "Unable to Load Geode!", "There was an unknown fatal error setting up " - "the internal mod and Geode can not be loaded." + "the internal mod and Geode can not be loaded." + internalSetupRes.unwrapErr() ); LoaderImpl::get()->reset(); return 1; } // set up loader, load mods, etc. - if (!LoaderImpl::get()->setup()) { + auto setupRes = LoaderImpl::get()->setup(); + if (!setupRes) { LoaderImpl::get()->platformMessageBox( "Unable to Load Geode!", "There was an unknown fatal error setting up " From 8a9a183e08eb5e2757cd13861af0f2d285a6859b Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Sat, 21 Jan 2023 22:16:16 +0200 Subject: [PATCH 25/31] update tuliphook version --- CMakeLists.txt | 2 +- loader/src/loader/LoaderImpl.hpp | 2 +- loader/src/loader/ModImpl.cpp | 7 ++----- loader/src/main.cpp | 24 ++++++++---------------- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7acaed9c..440b46fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,7 +123,7 @@ CPMAddPackage("gh:fmtlib/fmt#9.1.0") CPMAddPackage("gh:gulrak/filesystem#3e5b930") # Tulip hook (hooking) -CPMAddPackage("gh:geode-sdk/TulipHook#fd27e4a") +CPMAddPackage("gh:geode-sdk/TulipHook#52052be") target_link_libraries(${PROJECT_NAME} INTERFACE ghc_filesystem fmt TulipHookInclude GeodeCodegenSources) diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp index c96853db..e0527fbe 100644 --- a/loader/src/loader/LoaderImpl.hpp +++ b/loader/src/loader/LoaderImpl.hpp @@ -135,7 +135,7 @@ namespace geode { void addInternalHook(Hook* hook, Mod* mod); Mod* createInternalMod(); - void setupInternalMod(); + Result<> setupInternalMod(); }; class LoaderImpl { diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index b2a1bb79..855a6131 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -678,9 +678,6 @@ Mod* Loader::Impl::createInternalMod() { return mod; } -void Loader::Impl::setupInternalMod() { - auto setupRes = Mod::get()->m_impl->setup(); - if (!setupRes) { - log::error("Failed to setup internal mod! ({})", setupRes.unwrapErr()); - } +Result<> Loader::Impl::setupInternalMod() { + return Mod::get()->m_impl->setup(); } diff --git a/loader/src/main.cpp b/loader/src/main.cpp index 9e063073..4e6676ac 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -154,18 +154,6 @@ $execute { int geodeEntry(void* platformData) { // setup internals - auto intModSetupRes = ModImpl::getImpl(Mod::get())->setup(); - if (!intModSetupRes) { - LoaderImpl::get()->platformMessageBox( - "Unable to load Geode!", - "There was an unknown fatal error setting up " - "the internal mod representation and Geode can " - "not be loaded. " - "(" + intModSetupRes.unwrapErr() + ")" - ); - return 1; - } - if (!geode::core::hook::initialize()) { LoaderImpl::get()->platformMessageBox( "Unable to load Geode!", @@ -177,22 +165,26 @@ int geodeEntry(void* platformData) { } // set up internal mod, settings and data - if (!LoaderImpl::get()->setupInternalMod()) { + auto setupIntMod = LoaderImpl::get()->setupInternalMod(); + if (!setupIntMod) { LoaderImpl::get()->platformMessageBox( "Unable to Load Geode!", "There was an unknown fatal error setting up " - "the internal mod and Geode can not be loaded." + "the internal mod and Geode can not be loaded. " + "(" + setupIntMod.unwrapErr() + ")" ); LoaderImpl::get()->reset(); return 1; } // set up loader, load mods, etc. - if (!LoaderImpl::get()->setup()) { + auto setupRes = LoaderImpl::get()->setup(); + if (!setupRes) { LoaderImpl::get()->platformMessageBox( "Unable to Load Geode!", "There was an unknown fatal error setting up " - "the loader and Geode can not be loaded." + setupRes.unwrapErr() + "the loader and Geode can not be loaded. " + "(" + setupRes.unwrapErr() + ")" ); LoaderImpl::get()->reset(); return 1; From 9a476ce64da9b8cedc3a0995a7749f56224616d4 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 21 Jan 2023 23:36:14 +0300 Subject: [PATCH 26/31] visibility test --- CMakeLists.txt | 2 +- cmake/Platform.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7acaed9c..e5b52c71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,7 @@ add_custom_command( COMMAND echo codegen > ${GEODE_CODEGEN_PATH}/.stamp WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Run Codegen" - OUTPUT ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp ${GEODE_CODEGEN_PATH}/.stamp + OUTPUT ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp ${GEODE_CODEGEN_PATH}/Geode/GeneratedAddress.cpp ${GEODE_CODEGEN_PATH}/.stamp ) add_custom_target(CodegenRun diff --git a/cmake/Platform.cmake b/cmake/Platform.cmake index 61860272..4a8c4129 100644 --- a/cmake/Platform.cmake +++ b/cmake/Platform.cmake @@ -32,7 +32,7 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "MacOS") ) target_link_libraries(${PROJECT_NAME} INTERFACE curl "-framework Cocoa") - target_compile_options(${PROJECT_NAME} INTERFACE -fms-extensions #[[-Wno-deprecated]] -Wno-ignored-attributes -Os #[[-flto]] -fvisibility=internal) + target_compile_options(${PROJECT_NAME} INTERFACE -fms-extensions #[[-Wno-deprecated]] -Wno-ignored-attributes -Os #[[-flto]] #[[-fvisibility=internal]]) set(GEODE_PLATFORM_BINARY "Geode.dylib") From d2646947001d696fcabe81b635dbdb17b0645514 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 23 Jan 2023 16:53:43 +0200 Subject: [PATCH 27/31] update tuliphook to fix hooking cdecls --- CMakeLists.txt | 2 +- codegen/src/ModifyGen.cpp | 9 ++++- .../include/Geode/modify/AsStaticFunction.hpp | 39 ++++++++++++++++++- loader/src/hooks/MenuLayer.cpp | 2 + 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cb227ec..8d3fc211 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,7 +123,7 @@ CPMAddPackage("gh:fmtlib/fmt#9.1.0") CPMAddPackage("gh:gulrak/filesystem#3e5b930") # Tulip hook (hooking) -CPMAddPackage("gh:geode-sdk/TulipHook#52052be") +CPMAddPackage("gh:geode-sdk/TulipHook#65457c6") target_link_libraries(${PROJECT_NAME} INTERFACE ghc_filesystem fmt TulipHookInclude GeodeCodegenSources) diff --git a/codegen/src/ModifyGen.cpp b/codegen/src/ModifyGen.cpp index 674910da..c1542bbc 100644 --- a/codegen/src/ModifyGen.cpp +++ b/codegen/src/ModifyGen.cpp @@ -31,7 +31,7 @@ namespace geode::modifier {{ char const* statics_declare_identifier = R"GEN( #ifndef GEODE_STATICS_{function_name} #define GEODE_STATICS_{function_name} - GEODE_AS_STATIC_FUNCTION({function_name}) + {macro_name}({function_name}) #endif )GEN"; @@ -92,7 +92,12 @@ std::string generateModifyHeader(Root& root, ghc::filesystem::path const& single if (fn->type == FunctionType::Normal && !used.count(fn->name)) { used.insert(fn->name); statics += fmt::format( - format_strings::statics_declare_identifier, fmt::arg("function_name", fn->name) + format_strings::statics_declare_identifier, + fmt::arg("function_name", fn->name), + fmt::arg("macro_name", + (fn->is_virtual ? "GEODE_VIRTUAL_AS_STATIC_FUNCTION" : + "GEODE_AS_STATIC_FUNCTION") + ) ); } } diff --git a/loader/include/Geode/modify/AsStaticFunction.hpp b/loader/include/Geode/modify/AsStaticFunction.hpp index 2de3fc8c..feb10ee0 100644 --- a/loader/include/Geode/modify/AsStaticFunction.hpp +++ b/loader/include/Geode/modify/AsStaticFunction.hpp @@ -1,6 +1,7 @@ #pragma once #include "../utils/addresser.hpp" #include "Traits.hpp" +#include "../loader/Log.hpp" namespace geode::modifier { /** @@ -13,12 +14,48 @@ namespace geode::modifier { struct Impl {}; \ template \ struct Impl { \ - static Return GEODE_CDECL_CALL function(Params... params) { return Class2::FunctionName_(params...); } \ + static Return GEODE_CDECL_CALL function(Params... params) { \ + return Class2::FunctionName_(params...); \ + } \ }; \ template \ struct Impl { \ static Return GEODE_CDECL_CALL function(Class* self, Params... params) { \ auto self2 = addresser::rthunkAdjust(Function, self); \ + log::debug("{}", __FUNCTION__);\ + log::debug("self {} -> self2 {}", (void*)(self), (void*)(self2));\ + return self2->Class2::FunctionName_(params...); \ + } \ + }; \ + template \ + struct Impl { \ + static Return GEODE_CDECL_CALL function(Class const* self, Params... params) { \ + auto self2 = addresser::rthunkAdjust(Function, self); \ + log::debug("{}", __FUNCTION__);\ + log::debug("self {} -> self2 {}", (void*)(self), (void*)(self2));\ + return self2->Class2::FunctionName_(params...); \ + } \ + }; \ + static constexpr auto value = &Impl::function; \ + }; + +#define GEODE_VIRTUAL_AS_STATIC_FUNCTION(FunctionName_) \ + template \ + struct AsStaticFunction_##FunctionName_ { \ + template \ + struct Impl {}; \ + template \ + struct Impl { \ + static Return GEODE_CDECL_CALL function(Params... params) { \ + return Class2::FunctionName_(params...); \ + } \ + }; \ + template \ + struct Impl { \ + static Return GEODE_CDECL_CALL function(Class* self, Params... params) { \ + auto self2 = addresser::rthunkAdjust(Function, self); \ + log::debug("{}", __FUNCTION__);\ + log::debug("self {} -> self2 {}", (void*)(self), (void*)(self2));\ return self2->Class2::FunctionName_(params...); \ } \ }; \ diff --git a/loader/src/hooks/MenuLayer.cpp b/loader/src/hooks/MenuLayer.cpp index 889568e5..74cc96da 100644 --- a/loader/src/hooks/MenuLayer.cpp +++ b/loader/src/hooks/MenuLayer.cpp @@ -45,6 +45,8 @@ struct CustomMenuLayer : Modify { CCSprite* m_geodeButton; bool init() { + log::debug("this: {}", this); + if (!MenuLayer::init()) return false; // make sure to add the string IDs for nodes (Geode has no manual From 21e25ff3821282dce6444930634d3e6d53198e63 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 23 Jan 2023 19:31:38 +0200 Subject: [PATCH 28/31] fix thunk adjust --- CMakeLists.txt | 2 +- codegen/src/ModifyGen.cpp | 6 +--- .../include/Geode/modify/AsStaticFunction.hpp | 34 ------------------- loader/include/Geode/utils/addresser.hpp | 9 +++++ loader/include/Geode/utils/ranges.hpp | 3 ++ 5 files changed, 14 insertions(+), 40 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d3fc211..44174b90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,7 +123,7 @@ CPMAddPackage("gh:fmtlib/fmt#9.1.0") CPMAddPackage("gh:gulrak/filesystem#3e5b930") # Tulip hook (hooking) -CPMAddPackage("gh:geode-sdk/TulipHook#65457c6") +CPMAddPackage("gh:geode-sdk/TulipHook#9980bcf") target_link_libraries(${PROJECT_NAME} INTERFACE ghc_filesystem fmt TulipHookInclude GeodeCodegenSources) diff --git a/codegen/src/ModifyGen.cpp b/codegen/src/ModifyGen.cpp index c1542bbc..abe72588 100644 --- a/codegen/src/ModifyGen.cpp +++ b/codegen/src/ModifyGen.cpp @@ -31,7 +31,7 @@ namespace geode::modifier {{ char const* statics_declare_identifier = R"GEN( #ifndef GEODE_STATICS_{function_name} #define GEODE_STATICS_{function_name} - {macro_name}({function_name}) + GEODE_AS_STATIC_FUNCTION({function_name}) #endif )GEN"; @@ -94,10 +94,6 @@ std::string generateModifyHeader(Root& root, ghc::filesystem::path const& single statics += fmt::format( format_strings::statics_declare_identifier, fmt::arg("function_name", fn->name), - fmt::arg("macro_name", - (fn->is_virtual ? "GEODE_VIRTUAL_AS_STATIC_FUNCTION" : - "GEODE_AS_STATIC_FUNCTION") - ) ); } } diff --git a/loader/include/Geode/modify/AsStaticFunction.hpp b/loader/include/Geode/modify/AsStaticFunction.hpp index feb10ee0..e9570492 100644 --- a/loader/include/Geode/modify/AsStaticFunction.hpp +++ b/loader/include/Geode/modify/AsStaticFunction.hpp @@ -22,40 +22,6 @@ namespace geode::modifier { struct Impl { \ static Return GEODE_CDECL_CALL function(Class* self, Params... params) { \ auto self2 = addresser::rthunkAdjust(Function, self); \ - log::debug("{}", __FUNCTION__);\ - log::debug("self {} -> self2 {}", (void*)(self), (void*)(self2));\ - return self2->Class2::FunctionName_(params...); \ - } \ - }; \ - template \ - struct Impl { \ - static Return GEODE_CDECL_CALL function(Class const* self, Params... params) { \ - auto self2 = addresser::rthunkAdjust(Function, self); \ - log::debug("{}", __FUNCTION__);\ - log::debug("self {} -> self2 {}", (void*)(self), (void*)(self2));\ - return self2->Class2::FunctionName_(params...); \ - } \ - }; \ - static constexpr auto value = &Impl::function; \ - }; - -#define GEODE_VIRTUAL_AS_STATIC_FUNCTION(FunctionName_) \ - template \ - struct AsStaticFunction_##FunctionName_ { \ - template \ - struct Impl {}; \ - template \ - struct Impl { \ - static Return GEODE_CDECL_CALL function(Params... params) { \ - return Class2::FunctionName_(params...); \ - } \ - }; \ - template \ - struct Impl { \ - static Return GEODE_CDECL_CALL function(Class* self, Params... params) { \ - auto self2 = addresser::rthunkAdjust(Function, self); \ - log::debug("{}", __FUNCTION__);\ - log::debug("self {} -> self2 {}", (void*)(self), (void*)(self2));\ return self2->Class2::FunctionName_(params...); \ } \ }; \ diff --git a/loader/include/Geode/utils/addresser.hpp b/loader/include/Geode/utils/addresser.hpp index 93c2384b..ec4fe862 100644 --- a/loader/include/Geode/utils/addresser.hpp +++ b/loader/include/Geode/utils/addresser.hpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace geode::addresser { @@ -198,11 +199,19 @@ namespace geode::addresser { template inline F thunkAdjust(T func, F self) { + // do NOT delete the line below. + // doing so breaks thunk adjusting on windows. + // why? bruh idk + auto _ = *union_cast(&func); return (F)((intptr_t)self + Addresser::thunkOf(func)); } template inline F rthunkAdjust(T func, F self) { + // do NOT delete the line below. + // doing so breaks thunk adjusting on windows. + // why? bruh idk + auto _ = *union_cast(&func); return (F)((intptr_t)self - Addresser::thunkOf(func)); } #endif diff --git a/loader/include/Geode/utils/ranges.hpp b/loader/include/Geode/utils/ranges.hpp index d75d8289..0481285b 100644 --- a/loader/include/Geode/utils/ranges.hpp +++ b/loader/include/Geode/utils/ranges.hpp @@ -17,6 +17,9 @@ namespace std { } #endif +#undef min +#undef max + namespace geode::utils::ranges { template concept ValidConstContainer = requires(C const& c) { From e2548ab4afad2736c52ac5b36ec54189157bffa0 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 23 Jan 2023 19:37:09 +0200 Subject: [PATCH 29/31] i hate c++ syntax --- codegen/src/ModifyGen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen/src/ModifyGen.cpp b/codegen/src/ModifyGen.cpp index abe72588..b1e2e7c4 100644 --- a/codegen/src/ModifyGen.cpp +++ b/codegen/src/ModifyGen.cpp @@ -93,7 +93,7 @@ std::string generateModifyHeader(Root& root, ghc::filesystem::path const& single used.insert(fn->name); statics += fmt::format( format_strings::statics_declare_identifier, - fmt::arg("function_name", fn->name), + fmt::arg("function_name", fn->name) ); } } From e65f1184e73a81cf3c84d526541a18a629d3839c Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 23 Jan 2023 19:45:29 +0200 Subject: [PATCH 30/31] remove use of union_cast --- loader/include/Geode/utils/addresser.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/loader/include/Geode/utils/addresser.hpp b/loader/include/Geode/utils/addresser.hpp index ec4fe862..f0025603 100644 --- a/loader/include/Geode/utils/addresser.hpp +++ b/loader/include/Geode/utils/addresser.hpp @@ -10,7 +10,6 @@ #include #include #include -#include namespace geode::addresser { @@ -202,7 +201,7 @@ namespace geode::addresser { // do NOT delete the line below. // doing so breaks thunk adjusting on windows. // why? bruh idk - auto _ = *union_cast(&func); + auto _ = *(ptrdiff_t*)(&func); return (F)((intptr_t)self + Addresser::thunkOf(func)); } @@ -211,7 +210,7 @@ namespace geode::addresser { // do NOT delete the line below. // doing so breaks thunk adjusting on windows. // why? bruh idk - auto _ = *union_cast(&func); + auto _ = *(ptrdiff_t*)(&func); return (F)((intptr_t)self - Addresser::thunkOf(func)); } #endif From 9e52089a0187a6f1a807545fa206b61d08aab7c2 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 23 Jan 2023 19:51:51 +0200 Subject: [PATCH 31/31] whoops turns out union cast is required to make it work --- loader/include/Geode/utils/addresser.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/loader/include/Geode/utils/addresser.hpp b/loader/include/Geode/utils/addresser.hpp index f0025603..bf4ac936 100644 --- a/loader/include/Geode/utils/addresser.hpp +++ b/loader/include/Geode/utils/addresser.hpp @@ -10,6 +10,7 @@ #include #include #include +#include "../utils/casts.hpp" namespace geode::addresser { @@ -201,7 +202,7 @@ namespace geode::addresser { // do NOT delete the line below. // doing so breaks thunk adjusting on windows. // why? bruh idk - auto _ = *(ptrdiff_t*)(&func); + auto _ = *geode::cast::template union_cast(&func); return (F)((intptr_t)self + Addresser::thunkOf(func)); } @@ -210,7 +211,7 @@ namespace geode::addresser { // do NOT delete the line below. // doing so breaks thunk adjusting on windows. // why? bruh idk - auto _ = *(ptrdiff_t*)(&func); + auto _ = *geode::cast::template union_cast(&func); return (F)((intptr_t)self - Addresser::thunkOf(func)); } #endif