#pragma once #pragma warning(default : 4067) #pragma warning(disable : 4251) // dll-interface #pragma warning(disable : 4244) // narrowing conversion #include #include #include #include namespace geode { struct PlatformInfo { HMODULE m_hmod; }; } namespace geode::base { GEODE_NOINLINE inline uintptr_t get() { static uintptr_t base = reinterpret_cast(GetModuleHandle(0)); return base; } GEODE_NOINLINE inline uintptr_t getCocos() { static uintptr_t base = reinterpret_cast(GetModuleHandleA("libcocos2d.dll")); return base; } } namespace geode::cast { template struct ShrunkPointer { uint32_t m_ptrOffset; Type* into(uintptr_t base) { return reinterpret_cast(base + m_ptrOffset); } }; struct TypeDescriptorType { void* m_typeinfoTable; intptr_t m_spare; char m_typeDescriptorName[0x100]; }; struct ClassDescriptorType; struct BaseClassDescriptorType { ShrunkPointer m_typeDescriptor; int32_t m_numContainedBases; int32_t m_memberDisplacement[3]; int32_t m_attributes; ShrunkPointer m_classDescriptor; }; struct BaseClassArrayType { ShrunkPointer m_descriptorEntries[0x100]; }; struct ClassDescriptorType { int32_t m_signature; int32_t m_attributes; int32_t m_numBaseClasses; ShrunkPointer m_baseClassArray; }; struct CompleteLocatorType { int32_t m_signature; int32_t m_offset; int32_t m_cdOffset; ShrunkPointer m_typeDescriptor; ShrunkPointer m_classDescriptor; #ifdef GEODE_IS_X64 int32_t m_locatorOffset; #endif }; struct MetaPointerType { CompleteLocatorType* m_completeLocator; }; struct VftableType { void* m_vftable[0x100]; }; struct CompleteVftableType : MetaPointerType, VftableType {}; template inline After typeinfo_cast(Before ptr) { static_assert( std::is_polymorphic_v>, "Input is not a polymorphic type" ); if (!ptr) { return After(); } auto basePtr = dynamic_cast(ptr); auto vftable = *reinterpret_cast(basePtr); auto metaPtr = static_cast(static_cast(vftable)); auto afterDesc = reinterpret_cast(&typeid(std::remove_pointer_t)); auto afterIdent = static_cast(afterDesc->m_typeDescriptorName); #ifdef GEODE_IS_X64 auto locatorOffset = metaPtr->m_completeLocator->m_locatorOffset; auto base = reinterpret_cast(metaPtr->m_completeLocator) - locatorOffset; #else auto base = 0; #endif auto classDesc = metaPtr->m_completeLocator->m_classDescriptor.into(base); for (int32_t i = 0; i < classDesc->m_numBaseClasses; ++i) { auto entry = classDesc->m_baseClassArray.into(base)->m_descriptorEntries[i].into(base); auto optionIdent = static_cast( entry->m_typeDescriptor.into(base)->m_typeDescriptorName ); auto optionOffset = entry->m_memberDisplacement[0]; if (std::strcmp(afterIdent, optionIdent) == 0) { auto afterPtr = reinterpret_cast(basePtr) + optionOffset; return reinterpret_cast(afterPtr); } } return nullptr; } }