diff --git a/loader/include/Geode/platform/macos.hpp b/loader/include/Geode/platform/macos.hpp index 54c720fa..4c351cd7 100644 --- a/loader/include/Geode/platform/macos.hpp +++ b/loader/include/Geode/platform/macos.hpp @@ -81,7 +81,7 @@ namespace geode::cast { } inline void* traverseTypeinfoFor( - void* ptr, ClassTypeinfoType* typeinfo, char const* afterIdent + void* ptr, ClassTypeinfoType const* typeinfo, char const* afterIdent ) { DummySingleClass dummySingleClass; DummyMultipleClass dummyMultipleClass; @@ -93,11 +93,11 @@ namespace geode::cast { } } if (typeinfo->m_typeinfoVtable == typeinfoVtableOf(&dummySingleClass)) { - auto siTypeinfo = static_cast(typeinfo); + auto siTypeinfo = static_cast(typeinfo); return traverseTypeinfoFor(ptr, siTypeinfo->m_baseClassTypeinfo, afterIdent); } else if (typeinfo->m_typeinfoVtable == typeinfoVtableOf(&dummyMultipleClass)) { - auto vmiTypeinfo = static_cast(typeinfo); + auto vmiTypeinfo = static_cast(typeinfo); for (int i = 0; i < vmiTypeinfo->m_numBaseClass; ++i) { auto& entry = vmiTypeinfo->m_baseClasses[i]; auto optionPtr = reinterpret_cast(ptr) + entry.m_offset; @@ -109,20 +109,31 @@ namespace geode::cast { return nullptr; } + inline void* typeinfoCastInternal(void* ptr, ClassTypeinfoType const* beforeTypeinfo, ClassTypeinfoType const* afterTypeinfo, size_t hint) { + // we're not using either because uhhh idk + // hint is for diamond inheritance iirc which is never + // used in gd, so should be pretty safe to ignore + (void)beforeTypeinfo; + (void)hint; + + auto vftable = *reinterpret_cast(ptr); + auto dataPointer = static_cast(static_cast(vftable)); + auto typeinfo = dataPointer->m_typeinfo; + auto basePtr = static_cast(ptr) + dataPointer->m_offset; + + auto afterIdent = afterTypeinfo->m_typeinfoName; + + return traverseTypeinfoFor(basePtr, typeinfo, afterIdent); + } + template inline After typeinfo_cast(Before ptr) { static_assert( - std::is_polymorphic_v>, "Input is not a polymorphic type" + std::is_polymorphic_v> && std::is_polymorphic_v>, + "Input is not a polymorphic type" ); - auto basePtr = dynamic_cast(ptr); - auto vftable = *reinterpret_cast(basePtr); - auto typeinfo = - static_cast(static_cast(vftable))->m_typeinfo; - - auto afterTypeinfo = - reinterpret_cast(&typeid(std::remove_pointer_t)); - auto afterIdent = afterTypeinfo->m_typeinfoName; - - return static_cast(traverseTypeinfoFor(basePtr, typeinfo, afterIdent)); + auto beforeTypeinfo = reinterpret_cast(&typeid(std::remove_pointer_t)); + auto afterTypeinfo = reinterpret_cast(&typeid(std::remove_pointer_t)); + return static_cast(typeinfoCastInternal(ptr, beforeTypeinfo, afterTypeinfo, 0)); } } diff --git a/loader/src/hooks/DynamicCastFix.cpp b/loader/src/hooks/DynamicCastFix.cpp new file mode 100644 index 00000000..f0717118 --- /dev/null +++ b/loader/src/hooks/DynamicCastFix.cpp @@ -0,0 +1,20 @@ +#include + +#ifdef GEODE_IS_MACOS + +USE_GEODE_NAMESPACE(); + +#include +#include + +$execute { + // this replaces the call to __dynamic_cast with a call to our own + // this is needed because the transitions in cocos uses dynamic cast to check + // layers, which fail on user layers due to typeinfo not matching + (void)Mod::get()->patch( + reinterpret_cast(base::get() + 0x603948), + toByteArray(&cast::typeinfoCastInternal) + ); +} + +#endif \ No newline at end of file diff --git a/loader/src/hooks/handler_fixes.cpp b/loader/src/hooks/handler_fixes.cpp deleted file mode 100644 index ec872713..00000000 --- a/loader/src/hooks/handler_fixes.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// this is the fix for the dynamic_cast problems -// TODO: completely replace dynamic_cast on macos -#include - -#if defined(GEODE_IS_IOS) || defined(GEODE_IS_MACOS) -USE_GEODE_NAMESPACE(); - - #define HandlerFixFor(CCUtility) \ - struct CCUtility##HandlerFix : Modify { \ - void destructor() { \ - if (m_pDelegate) { \ - cocos2d::CCObject* pObject = base_cast(m_pDelegate); \ - if (pObject) { \ - pObject->release(); \ - } \ - } \ - } \ - \ - bool initWithDelegate(cocos2d::CCUtility##Delegate* pDelegate) { \ - cocos2d::CCObject* pObject = base_cast(pDelegate); \ - if (pObject) { \ - m_pDelegate = pDelegate; \ - pObject->retain(); \ - return true; \ - } \ - return false; \ - } \ - \ - static cocos2d::CCUtility##Handler* handlerWithDelegate( \ - cocos2d::CCUtility##Delegate* pDelegate \ - ) { \ - cocos2d::CCUtility##Handler* pHandler = new cocos2d::CCUtility##Handler(); \ - \ - if (pHandler) { \ - if (pHandler->initWithDelegate(pDelegate)) { \ - pHandler->autorelease(); \ - } \ - else { \ - CC_SAFE_RELEASE_NULL(pHandler); \ - pHandler = CCUtility##Handler::handlerWithDelegate(pDelegate); \ - } \ - } \ - \ - return pHandler; \ - } \ - } - // clang-format off -#include -HandlerFixFor(CCKeypad); -#include -HandlerFixFor(CCKeyboard); -#include -HandlerFixFor(CCMouse); - -#include -struct CCTargetedTouchHandlerFix : Modify { - void destructor() { - if (m_pDelegate) { - cocos2d::CCObject* pObject = base_cast(m_pDelegate); - if (pObject) { - // the entire destructor - pObject->release(); - CC_SAFE_RELEASE(m_pClaimedTouches); - } - } - } - - bool initWithDelegate(cocos2d::CCTouchDelegate *pDelegate, int nPriority, bool bSwallow) { - cocos2d::CCObject* pObject = base_cast(pDelegate); - if (pObject) { - m_pDelegate = pDelegate; - pObject->retain(); - - m_nPriority = nPriority; - m_nEnabledSelectors = 0; - - m_pClaimedTouches = new cocos2d::CCSet(); - m_bSwallowsTouches = bSwallow; - return true; - } - return false; - } - - static cocos2d::CCTargetedTouchHandler* handlerWithDelegate(cocos2d::CCTouchDelegate *pDelegate, int nPriority, bool bSwallow) { - cocos2d::CCTargetedTouchHandler* pHandler = new cocos2d::CCTargetedTouchHandler(); - - if (pHandler) { - if (pHandler->initWithDelegate(pDelegate, nPriority, bSwallow)) { - pHandler->autorelease(); - } - else { - CC_SAFE_RELEASE_NULL(pHandler); - pHandler = CCTargetedTouchHandler::handlerWithDelegate(pDelegate, nPriority, bSwallow); - } - } - - return pHandler; - } -}; - -#include -struct CCStandardTouchHandlerFix : Modify { - void destructor() { - if (m_pDelegate) { - cocos2d::CCObject* pObject = base_cast(m_pDelegate); - if (pObject) { - // the entire destructor - pObject->release(); - } - } - } - - bool initWithDelegate(cocos2d::CCTouchDelegate *pDelegate, int nPriority) { - cocos2d::CCObject* pObject = base_cast(pDelegate); - if (pObject) { - m_pDelegate = pDelegate; - pObject->retain(); - - m_nPriority = nPriority; - m_nEnabledSelectors = 0; - return true; - } - return false; - } - - static cocos2d::CCStandardTouchHandler* handlerWithDelegate(cocos2d::CCTouchDelegate *pDelegate, int nPriority) { - cocos2d::CCStandardTouchHandler* pHandler = new cocos2d::CCStandardTouchHandler(); - if (pHandler) { - if (pHandler->initWithDelegate(pDelegate, nPriority)) { - pHandler->autorelease(); - } - else { - CC_SAFE_RELEASE_NULL(pHandler); - pHandler = CCStandardTouchHandler::handlerWithDelegate(pDelegate, nPriority); - } - } - - return pHandler; - } -}; - -// clang-format on - -#endif