@@ -10,22 +10,6 @@ namespace { namespace format_strings {
1010
1111using namespace geode;
1212using namespace geode::modifier;
13- using cocos2d::CCDestructor;
14-
15- std::unordered_map<void*, bool>& CCDestructor::destructorLock() {{
16- static thread_local std::unordered_map<void*, bool> ret;
17- return ret;
18- }}
19- bool& CCDestructor::globalLock() {{
20- static thread_local bool ret = false;
21- return ret;
22- }}
23- bool& CCDestructor::lock(void* self) {
24- return destructorLock()[self];
25- }
26- CCDestructor::~CCDestructor() {{
27- destructorLock().erase(this);
28- }}
2913
3014auto wrapFunction(uintptr_t address, tulip::hook::WrapperMetadata const& metadata) {
3115 auto wrapped = geode::hook::createWrapper(reinterpret_cast<void*>(address), metadata);
@@ -34,11 +18,6 @@ auto wrapFunction(uintptr_t address, tulip::hook::WrapperMetadata const& metadat
3418 }}
3519 return wrapped.unwrap();
3620}
37-
38- // So apparently Clang considers cdecl to return floats through ST0, whereas
39- // MSVC thinks they are returned through XMM0. This has caused a lot of pain
40- // and misery for me
41-
4221)GEN" ;
4322
4423 constexpr char const * declare_member = R"GEN(
@@ -79,32 +58,37 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na
7958{class_name}::{function_name}({parameters}) {{
8059 // basically we destruct it once by calling the gd function,
8160 // then lock it, so that other gd destructors dont get called
82- if (CCDestructor::lock(this)) return;
83- using FunctionType = void(*)({class_name}*{parameter_comma}{parameter_types});
84- static auto func = wrapFunction({address_inline}, tulip::hook::WrapperMetadata{{
85- .m_convention = geode::hook::createConvention(tulip::hook::TulipConvention::{convention}),
86- .m_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)),
87- }});
88- reinterpret_cast<FunctionType>(func)(this{parameter_comma}{arguments});
89- // we need to construct it back so that it uhhh ummm doesnt crash
90- // while going to the child destructors
91- auto thing = new (this) {class_name}(geode::CutoffConstructor, sizeof({class_name}));
92- CCDestructor::lock(this) = true;
61+ if (!geode::DestructorLock::isLocked(this)) {{
62+ using FunctionType = void(*)({class_name}*{parameter_comma}{parameter_types});
63+ static auto func = wrapFunction({address_inline}, tulip::hook::WrapperMetadata{{
64+ .m_convention = geode::hook::createConvention(tulip::hook::TulipConvention::{convention}),
65+ .m_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)),
66+ }});
67+ reinterpret_cast<FunctionType>(func)(this{parameter_comma}{arguments});
68+
69+ // we need to construct it back so that it uhhh ummm doesnt crash
70+ // while going to the child destructors
71+ auto thing = new (this) {class_name}(geode::CutoffConstructor, sizeof({class_name}));
72+ geode::DestructorLock::addLock(this);
73+ }}
9374}}
9475)GEN" ;
9576
9677 constexpr char const * declare_destructor_baseless = R"GEN(
9778{class_name}::{function_name}({parameters}) {{
9879 // basically we destruct it once by calling the gd function,
99- // then lock it, so that other gd destructors dont get called
100- if (CCDestructor::lock(this)) return;
101- using FunctionType = void(*)({class_name}*{parameter_comma}{parameter_types});
102- static auto func = wrapFunction({address_inline}, tulip::hook::WrapperMetadata{{
103- .m_convention = geode::hook::createConvention(tulip::hook::TulipConvention::{convention}),
104- .m_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)),
105- }});
106- reinterpret_cast<FunctionType>(func)(this{parameter_comma}{arguments});
107- CCDestructor::lock(this) = true;
80+ // then we release the lock because there are no other destructors after this
81+ if (!geode::DestructorLock::isLocked(this)) {{
82+ using FunctionType = void(*)({class_name}*{parameter_comma}{parameter_types});
83+ static auto func = wrapFunction({address_inline}, tulip::hook::WrapperMetadata{{
84+ .m_convention = geode::hook::createConvention(tulip::hook::TulipConvention::{convention}),
85+ .m_abstract = tulip::hook::AbstractFunction::from(FunctionType(nullptr)),
86+ }});
87+ reinterpret_cast<FunctionType>(func)(this{parameter_comma}{arguments});
88+ }}
89+ else {{
90+ geode::DestructorLock::removeLock(this);
91+ }}
10892}}
10993)GEN" ;
11094
@@ -113,8 +97,9 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na
11397 // here we construct it as normal as we can, then destruct it
11498 // using the generated functions. this ensures no memory gets leaked
11599 // no crashes :pray:
116- CCDestructor::lock (this) = true ;
100+ geode::DestructorLock::addLock (this);
117101 {class_name}::~{unqualified_class_name}();
102+
118103 using FunctionType = void(*)({class_name}*{parameter_comma}{parameter_types});
119104 static auto func = wrapFunction({address_inline}, tulip::hook::WrapperMetadata{{
120105 .m_convention = geode::hook::createConvention(tulip::hook::TulipConvention::{convention}),
@@ -165,6 +150,10 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na
165150)GEN" ;
166151}}
167152
153+ bool areSuperclassesEmpty (Class const & c) {
154+ return c.superclasses .empty () || (c.superclasses .size () == 1 && c.superclasses [0 ].find (" CCCopying" ) != std::string::npos);
155+ }
156+
168157std::string generateBindingSource (Root const & root, bool skipPugixml) {
169158 std::string output (format_strings::source_start);
170159
@@ -237,7 +226,7 @@ std::string generateBindingSource(Root const& root, bool skipPugixml) {
237226 if (codegen::platformNumber (fn->binds ) == 0x9999999 ) {
238227 used_declare_format = format_strings::declare_unimplemented_error;
239228 }
240- else if (codegen::getStatus (*fn) != BindStatus::NeedsBinding && ! codegen::shouldAndroidBind ( fn)) {
229+ else if (codegen::getStatus (*fn) != BindStatus::NeedsBinding && codegen::getStatus (* fn) != BindStatus::NeedsRebinding ) {
241230 continue ;
242231 }
243232
@@ -247,15 +236,15 @@ std::string generateBindingSource(Root const& root, bool skipPugixml) {
247236 used_declare_format = format_strings::declare_member;
248237 break ;
249238 case FunctionType::Ctor:
250- if (c. superclasses . empty ( )) {
239+ if (areSuperclassesEmpty (c )) {
251240 used_declare_format = format_strings::declare_constructor_begin;
252241 }
253242 else {
254243 used_declare_format = format_strings::declare_constructor;
255244 }
256245 break ;
257246 case FunctionType::Dtor:
258- used_declare_format = c. superclasses . empty ( ) ? format_strings::declare_destructor_baseless : format_strings::declare_destructor;
247+ used_declare_format = areSuperclassesEmpty (c ) ? format_strings::declare_destructor_baseless : format_strings::declare_destructor;
259248 break ;
260249 }
261250
0 commit comments