diff --git a/loader/include/Geode/platform/ItaniumCast.hpp b/loader/include/Geode/platform/ItaniumCast.hpp index 93cd024e1..8f90d1797 100644 --- a/loader/include/Geode/platform/ItaniumCast.hpp +++ b/loader/include/Geode/platform/ItaniumCast.hpp @@ -1,8 +1,6 @@ #pragma once namespace geode::cast { - using uinthalf_t = uint32_t; - using inthalf_t = int32_t; struct DummyClass { virtual ~DummyClass() {} @@ -14,8 +12,10 @@ namespace geode::cast { struct DummyMultipleClass : DummySingleClass, DummyClass2 {}; + struct VtableType; + struct ClassTypeinfoType { - void** m_typeinfoVtable; + VtableType* m_typeinfoVtable; char const* m_typeinfoName; }; @@ -23,16 +23,17 @@ namespace geode::cast { ClassTypeinfoType* m_baseClassTypeinfo; }; -#pragma pack(push, 1) - struct MultipleClassSingleEntryType { ClassTypeinfoType* m_baseClassTypeinfo; - uint8_t m_visibilityFlag; - inthalf_t m_offset; - uint8_t m_padding[sizeof(inthalf_t) - 1]; - }; + intptr_t m_metadata; -#pragma pack(pop) + uint8_t visibilityFlag() const { + return m_metadata & 0xFF; + } + intptr_t offset() const { + return m_metadata >> 8; + } + }; struct MultipleClassTypeinfoType : ClassTypeinfoType { uint32_t m_flags; @@ -41,7 +42,7 @@ namespace geode::cast { }; struct VtableTypeinfoType { - inthalf_t m_offset; + intptr_t m_offset; ClassTypeinfoType* m_typeinfo; }; @@ -51,36 +52,25 @@ namespace geode::cast { struct CompleteVtableType : VtableTypeinfoType, VtableType {}; - inline void** typeinfoVtableOf(void* ptr) { - auto vftable = *reinterpret_cast(ptr); - - auto typeinfoPtr = - static_cast(static_cast(vftable)); - - return typeinfoPtr->m_typeinfo->m_typeinfoVtable; - } - inline void* traverseTypeinfoFor( void* ptr, ClassTypeinfoType const* typeinfo, char const* afterIdent ) { - DummySingleClass dummySingleClass; - DummyMultipleClass dummyMultipleClass; - { auto optionIdent = typeinfo->m_typeinfoName; if (std::strcmp(optionIdent, afterIdent) == 0) { return ptr; } } - if (typeinfo->m_typeinfoVtable == typeinfoVtableOf(&dummySingleClass)) { + auto typeinfoVtableName = static_cast(typeinfo->m_typeinfoVtable)->m_typeinfo->m_typeinfoName; + if (std::strcmp(typeinfoVtableName, "N10__cxxabiv120__si_class_type_infoE") == 0) { auto siTypeinfo = static_cast(typeinfo); return traverseTypeinfoFor(ptr, siTypeinfo->m_baseClassTypeinfo, afterIdent); } - else if (typeinfo->m_typeinfoVtable == typeinfoVtableOf(&dummyMultipleClass)) { + else if (std::strcmp(typeinfoVtableName, "N10__cxxabiv121__vmi_class_type_infoE") == 0) { 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; + auto optionPtr = reinterpret_cast(ptr) + entry.offset(); auto ret = traverseTypeinfoFor(optionPtr, entry.m_baseClassTypeinfo, afterIdent); if (ret != nullptr) return ret; } diff --git a/loader/include/Geode/platform/android.hpp b/loader/include/Geode/platform/android.hpp index e19402bcf..31c7edeb9 100644 --- a/loader/include/Geode/platform/android.hpp +++ b/loader/include/Geode/platform/android.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include "ItaniumCast.hpp" namespace geode { struct PlatformInfo { @@ -12,10 +13,3 @@ namespace geode::base { /*GEODE_NOINLINE inline*/ uintptr_t get(); } -namespace geode::cast { - template - After typeinfo_cast(Before ptr) { - // yall have symbols smh - return dynamic_cast(ptr); - } -} diff --git a/loader/src/hooks/DynamicCastFix.cpp b/loader/src/hooks/DynamicCastFix.cpp index 3986eeae4..5a17e56fa 100644 --- a/loader/src/hooks/DynamicCastFix.cpp +++ b/loader/src/hooks/DynamicCastFix.cpp @@ -1,19 +1,20 @@ #include - -#ifdef GEODE_IS_MACOS +#include using namespace geode::prelude; - #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 + #if defined(GEODE_IS_MACOS) + (void)Mod::get()->patch( + reinterpret_cast(base::get() + 0x603948), toByteArray(&cast::typeinfoCastInternal) + ); + #elif defined(GEODE_IS_ANDROID) + (void)Mod::get()->addHook(reinterpret_cast(base::get() + 0x519a8c), &cast::typeinfoCastInternal, "__dynamic_cast"); + #endif + + +} \ No newline at end of file