diff --git a/codegen/src/AddressGen.cpp b/codegen/src/AddressGen.cpp index 295ccbde..0e969dbe 100644 --- a/codegen/src/AddressGen.cpp +++ b/codegen/src/AddressGen.cpp @@ -1,4 +1,5 @@ #include "Shared.hpp" +#include "AndroidSymbol.hpp" namespace { namespace format_strings { @@ -120,9 +121,16 @@ std::string generateAddressHeader(Root const& root) { address_str = fmt::format("base::get() + 0x{:x}", codegen::platformNumber(fn->binds)); } } + else if (codegen::shouldAndroidBind(fn)) { + auto const mangled = generateAndroidSymbol(c, fn); + address_str = fmt::format( + "reinterpret_cast(dlsym(reinterpret_cast(geode::base::get()), \"{}\"))", + mangled + ); + } else if (codegen::getStatus(field) == BindStatus::Binded && fn->prototype.type == FunctionType::Normal) { address_str = fmt::format( - "0/*addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))*/", + "addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))", str_if("Non", !fn->prototype.is_virtual), codegen::getParameterTypes(fn->prototype), field.parent, diff --git a/codegen/src/AndroidSymbol.hpp b/codegen/src/AndroidSymbol.hpp new file mode 100644 index 00000000..dbb936e5 --- /dev/null +++ b/codegen/src/AndroidSymbol.hpp @@ -0,0 +1,143 @@ +#pragma once + +#include "Shared.hpp" + +#include +#include +#include +#include + +std::string mangleIdent(std::string_view str) { + if (str.find("::") != -1) { + std::string result = "N"; + auto s = str; + do { + const auto i = s.find("::"); + const auto t = s.substr(0, i); + result += std::to_string(t.size()) + std::string(t); + if (i == -1) s = ""; + else + s = s.substr(i + 2); + } while(s.size()); + return result + "E"; + } else { + return std::to_string(str.size()) + std::string(str); + } +}; + +std::string intToString(unsigned int value, unsigned int radix) { + static constexpr char base36[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + std::string result; + do { + unsigned int remainder = value % radix; + value /= radix; + result.insert(result.begin(), base36[remainder]); + } while (value); + return result; +} + +std::string lookForSeen(std::vector& seen, std::string mangled) { + for (int i = 0; i < seen.size(); ++i) { + if (seen[i] == mangled) { + if (i == 0) return "S_"; + // yes, its base 36 + return "S" + intToString(i - 1, 36) + "_"; + } + } + return ""; +} + +std::string subsSeen(std::vector& seen, std::string mangled, bool subs) { + if (!subs) return mangled; + if (mangled.empty()) return mangled; + if (auto x = lookForSeen(seen, mangled); !x.empty()) return x; + seen.push_back(mangled); + return mangled; +} + +std::string mangleType(std::vector& seen, std::string name, bool subs = true) { + if (name == "int") return "i"; + if (name == "float") return "f"; + if (name == "bool") return "b"; + if (name == "char") return "c"; + if (name == "gd::string") return "Ss"; + if (name == "cocos2d::ccColor3B") return mangleType(seen, "cocos2d::_ccColor3B", subs); + // too lazy + if (name == "gd::map") return "St3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE"; + if (name == "cocos2d::SEL_MenuHandler") { + const auto a = mangleType(seen, "cocos2d::CCObject", subs); + const auto b = mangleType(seen, "cocos2d::CCObject*", subs); + const auto fnptr = subsSeen(seen, "Fv" + b + "E", subs); + return subsSeen(seen, "M" + a + fnptr, subs); + } + if (name.find('*') == name.size() - 1) { + auto inner = mangleType(seen, name.substr(0, name.size() - 1), false); + if (auto x = lookForSeen(seen, "P" + inner); !x.empty()) return x; + inner = mangleType(seen, name.substr(0, name.size() - 1), subs); + return subsSeen(seen, "P" + inner, subs); + } + if (name.find('&') == name.size() - 1) { + auto inner = mangleType(seen, name.substr(0, name.size() - 1), false); + if (auto x = lookForSeen(seen, "R" + inner); !x.empty()) return x; + inner = mangleType(seen, name.substr(0, name.size() - 1), subs); + return subsSeen(seen, "R" + inner, subs); + } + if (auto i = name.find("const"); i != -1) { + std::string inner; + // at the end of the name + if (i == name.size() - 5) { + inner = mangleType(seen, name.substr(0, i - 1)); + } else if (i == 0) { + inner = mangleType(seen, name.substr(6)); + } else { + inner = "v"; + std::cout << "um " << name << std::endl; + } + return subsSeen(seen, "K" + inner, subs); + } + + if (name.find("::") != -1) { + std::string result = ""; + std::string substituted = ""; + auto s = name; + do { + const auto i = s.find("::"); + const auto t = s.substr(0, i); + auto part = std::to_string(t.size()) + std::string(t); + if (auto x = lookForSeen(seen, result + part); !x.empty()) { + substituted = x; + } else { + substituted = subsSeen(seen, substituted + part, subs); + } + result += part; + + if (i == -1) s = ""; + else s = s.substr(i + 2); + } while(s.size()); + if (substituted.size() == 3 && substituted[0] == 'S') + return substituted; + return "N" + substituted + "E"; + } else { + return subsSeen(seen, mangleIdent(name), subs); + } +}; + +std::string generateAndroidSymbol(const Class& clazz, const FunctionBindField* fn) { + auto& decl = fn->prototype; + + std::string mangledSymbol = "_Z" + mangleIdent(clazz.name + "::" + decl.name); + if (decl.args.empty()) { + mangledSymbol += "v"; + } else { + std::vector seen; + static constexpr auto firstPart = [](std::string_view str, std::string_view sep) { + return str.substr(0, str.find(sep)); + }; + // this is S_ + seen.push_back(mangleIdent(firstPart(clazz.name, "::"))); + for (auto& [ty, _] : decl.args) { + mangledSymbol += mangleType(seen, ty.name); + } + } + return mangledSymbol; +} \ No newline at end of file diff --git a/codegen/src/Shared.hpp b/codegen/src/Shared.hpp index c8e07b6f..a2a69443 100644 --- a/codegen/src/Shared.hpp +++ b/codegen/src/Shared.hpp @@ -129,6 +129,15 @@ namespace codegen { return BindStatus::Unbindable; } + inline bool shouldAndroidBind(const FunctionBindField* fn) { + if (codegen::platform == Platform::Android) { + for (auto& [type, name] : fn->prototype.args) { + if (can_find(type.name, "gd::")) return true; + } + } + return false; + } + inline BindStatus getStatus(Field const& field) { return getStatusWithPlatform(codegen::platform, field); } diff --git a/codegen/src/SourceGen.cpp b/codegen/src/SourceGen.cpp index 000dd6dd..230a31fc 100644 --- a/codegen/src/SourceGen.cpp +++ b/codegen/src/SourceGen.cpp @@ -198,10 +198,10 @@ std::string generateBindingSource(Root const& root) { ) { used_declare_format = format_strings::declare_virtual_error; } - else if (codegen::getStatus(f) != BindStatus::NeedsBinding) { + else if (codegen::getStatus(f) != BindStatus::NeedsBinding && !codegen::shouldAndroidBind(fn)) { continue; } - + if (!used_declare_format) { switch (fn->prototype.type) {