diff --git a/loader/include/Geode/utils/addresser.hpp b/loader/include/Geode/utils/addresser.hpp index 42ecd82a..dfd26877 100644 --- a/loader/include/Geode/utils/addresser.hpp +++ b/loader/include/Geode/utils/addresser.hpp @@ -27,6 +27,9 @@ namespace geode::addresser { template <typename T, typename F> inline F rthunkAdjust(T func, F self); + template <class Class> + concept HasCreate = requires() { Class::create(); }; + class GEODE_DLL Addresser final { template <char C> struct SingleInheritance { @@ -63,6 +66,41 @@ namespace geode::addresser { return thunk; } + // I gave up + template <class Class> + requires(HasCreate<Class>) + static Class* generateInstance() { + return Class::create(); + } + + template <class Class> + requires(!HasCreate<Class>) + static Class* generateInstance() { + // Create a random memory block with the size of Class + // Assign a pointer to that block and cast it to type Class* + uint8_t dum[sizeof(Class)]{}; + auto ptr = reinterpret_cast<Class*>(dum); + // Now you have a object of Class that actually isn't an object of Class and is just a + // random memory But C++ doesn't know that of course So now you can copy an object + // that wasn't there in the first place + // ((oh also get the offsets of the virtual tables)) + auto ins = new Class(*ptr); + // this is how the first human was made + return ins; + } + + template <class Class> + requires(HasCreate<Class>) + static void releaseInstance(Class* ins) {} + + template <class Class> + requires(!HasCreate<Class>) + static void releaseInstance(Class* ins) { + // And we delete the new instance because we are good girls + // and we don't leak memories + operator delete(ins); + } + /** * Specialized functionss */ @@ -72,26 +110,9 @@ namespace geode::addresser { ) { using geode::cast::reference_cast; - // exceptions, can't be bothered to have a proper fix because there is None - T* ins; - if constexpr (std::is_same_v<T, cocos2d::CCSet>) { - ins = cocos2d::CCSet::create(); - } - else { - // Create a random memory block with the size of T - // Assign a pointer to that block and cast it to type T* - uint8_t dum[sizeof(T)]{}; - auto ptr = reinterpret_cast<T*>(dum); - // Now you have a object of T that actually isn't an object of T and is just a - // random memory But C++ doesn't know that of course So now you can copy an object - // that wasn't there in the first place - // ((oh also get the offsets of the virtual tables)) - ins = new T(*ptr); - // this is how the first human was made - } - auto index = indexOf(func); auto thunk = thunkOf(func); + auto ins = generateInstance<T>(); // log::debug("[[" + utils::intToHex((void*)ins) + " + " + utils::intToHex(thunk) + "] + // " + utils::intToHex(index) + "]"); @@ -112,10 +133,7 @@ namespace geode::addresser { address = *reinterpret_cast<uintptr_t*>(address); } #endif - - // And we delete the new instance because we are good girls - // and we don't leak memories - operator delete(ins); + releaseInstance<T>(ins); return address; }