implement loader for android

compilation still won't work, pending implementations for gdstl/codegen/tuliphook. the first two should be mostly done already. may also be good to get FileWatcher, crashlog, and the file picker implemented but they aren't necessary

the libcurl.a and libssl.a files were built using
https://github.com/ibaoger/libcurl-android. they are placed in the link/android folder because putting them in the link folder confused the macOS build.

once built, the geode binary should be loaded after nativeSetApkPath is ran (otherwise the directory setup crashes). in the future it would be nice if the internal mod also did save data path redirection, as base GD is incapable of doing this

Co-authored-by: mat <26722564+matcool@users.noreply.github.com>
This commit is contained in:
qimiko 2023-06-05 17:42:22 -07:00
parent cb016214cd
commit 041a98ee4d
No known key found for this signature in database
GPG key ID: D2D404DD810FE0E3
17 changed files with 217 additions and 4 deletions

View file

@ -7,6 +7,8 @@ if (NOT DEFINED GEODE_TARGET_PLATFORM)
endif()
elseif(WIN32)
set(GEODE_TARGET_PLATFORM "Win32")
elseif(ANDROID)
set(GEODE_TARGET_PLATFORM "Android")
else()
message(FATAL_ERROR "Unable to detect platform, please set GEODE_TARGET_PLATFORM in the root CMake file.")
endif()
@ -64,5 +66,17 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "Win32")
# Windows links against .lib and not .dll
set(GEODE_PLATFORM_BINARY "Geode.lib")
elseif (GEODE_TARGET_PLATFORM STREQUAL "Android")
message(FATAL_ERROR "IDK figure it out")
set_target_properties(${PROJECT_NAME} PROPERTIES
SYSTEM_NAME Android
)
target_link_libraries(${PROJECT_NAME} INTERFACE
${GEODE_LOADER_PATH}/include/link/android/libcocos2dcpp.so
${GEODE_LOADER_PATH}/include/link/android/libcurl.a
${GEODE_LOADER_PATH}/include/link/android/libssl.a
${GEODE_LOADER_PATH}/include/link/android/libcrypto.a
log
)
set(GEODE_PLATFORM_BINARY "Geode.so")
endif()

View file

@ -43,6 +43,7 @@ file(GLOB SOURCES CONFIGURE_DEPENDS
src/internal/*.cpp
src/platform/mac/*.cpp
src/platform/ios/*.cpp
src/platform/android/*.cpp
src/loader/*.cpp
src/main.cpp
src/utils/*.cpp
@ -87,6 +88,13 @@ elseif(APPLE)
list(APPEND SOURCES ${MAC_SOURCES})
list(APPEND SOURCES ${OBJC_SOURCES})
elseif(ANDROID)
file(GLOB ANDROID_SOURCES CONFIGURE_DEPENDS
src/platform/android/*.cpp
)
list(APPEND SOURCES ${ANDROID_SOURCES})
endif()
# Embed version info in binary

View file

@ -80,6 +80,8 @@ namespace geode {
GEODE_MACOS(GEODE_FILL_CONSTRUCTOR(Class_, 0){}) \
GEODE_IOS(GEODE_FILL_CONSTRUCTOR(Class_, 0){}) \
GEODE_WINDOWS(Class_(geode::CutoffConstructorType, size_t fill) \
: Class_() {}) \
GEODE_ANDROID(Class_(geode::CutoffConstructorType, size_t fill) \
: Class_() {})
#define GEODE_CUTOFF_CONSTRUCTOR_COCOS(Class_, Base_) \
@ -88,6 +90,8 @@ namespace geode {
GEODE_IOS(Class_(geode::CutoffConstructorType, size_t fill) \
: Base_(geode::CutoffConstructor, fill){}) \
GEODE_WINDOWS(Class_(geode::CutoffConstructorType, size_t fill) \
: Class_() {}) \
GEODE_ANDROID(Class_(geode::CutoffConstructorType, size_t fill) \
: Class_() {})
#define GEODE_CUTOFF_CONSTRUCTOR_GD(Class_, Base_) \
@ -96,10 +100,13 @@ namespace geode {
GEODE_MACOS(Class_(geode::CutoffConstructorType, size_t fill) \
: Base_(geode::CutoffConstructor, fill){}) \
GEODE_IOS(Class_(geode::CutoffConstructorType, size_t fill) \
: Base_(geode::CutoffConstructor, fill){}) \
GEODE_ANDROID(Class_(geode::CutoffConstructorType, size_t fill) \
: Base_(geode::CutoffConstructor, fill){})
#define GEODE_CUTOFF_CONSTRUCTOR_CUTOFF(Class_, Base_) \
GEODE_WINDOWS(GEODE_FILL_CONSTRUCTOR(Class_, sizeof(Base_)) : Base_(){}) \
GEODE_ANDROID(GEODE_FILL_CONSTRUCTOR(Class_, sizeof(Base_)) : Base_(){}) \
GEODE_MACOS(Class_(geode::CutoffConstructorType, size_t fill) \
: Base_(geode::CutoffConstructor, fill){}) \
GEODE_IOS(Class_(geode::CutoffConstructorType, size_t fill) \

Binary file not shown.

View file

@ -20,7 +20,7 @@ public:
@brief Callback by CCDirector to limit FPS.
@interval The time, expressed in seconds, between current frame and next.
*/
void setAnimationInterval(double interval);
virtual void setAnimationInterval(double interval) override;
/**
@brief Run the message loop.
@ -39,12 +39,12 @@ public:
@brief Get current language config
@return Current language config
*/
virtual ccLanguageType getCurrentLanguage();
virtual ccLanguageType getCurrentLanguage() override;
/**
@brief Get target platform
*/
virtual TargetPlatform getTargetPlatform();
virtual TargetPlatform getTargetPlatform() override;
virtual void openURL(char const* url) override;

View file

@ -2,6 +2,12 @@
#include <dlfcn.h>
namespace geode {
struct PlatformInfo {
void* m_so;
};
}
namespace geode::base {
GEODE_NOINLINE inline uintptr_t get() {
static uintptr_t base = reinterpret_cast<uintptr_t>(dlopen("libcocos2dcpp.so", RTLD_LAZY));

View file

@ -2,6 +2,7 @@
#include <Geode/DefaultInclude.hpp>
#include <memory>
#include <concepts>
namespace geode::utils {

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -54,6 +54,15 @@ extern "C" __attribute__((visibility("default"))) void dynamicTrigger() {
// remove when we can figure out how to not remove it
auto dynamicTriggerRef = &dynamicTrigger;
#elif defined(GEODE_IS_ANDROID)
#include <jni.h>
extern "C" [[gnu::visibility("default")]] jint JNI_OnLoad(JavaVM* vm, void* reserved) {
geodeEntry(nullptr);
return JNI_VERSION_1_1;
}
#elif defined(GEODE_IS_WINDOWS)
#include <Windows.h>

View file

@ -0,0 +1,27 @@
#include <FileWatcher.hpp>
#ifdef GEODE_IS_ANDROID
FileWatcher::FileWatcher(
ghc::filesystem::path const& file, FileWatchCallback callback, ErrorCallback error
) {
m_filemode = ghc::filesystem::is_regular_file(file);
m_platformHandle = nullptr;
m_file = file;
m_callback = callback;
m_error = error;
}
FileWatcher::~FileWatcher() {
}
void FileWatcher::watch() {
// TODO: setup inotify or something
}
bool FileWatcher::watching() const {
return false;
}
#endif

View file

@ -0,0 +1,55 @@
#include <Geode/loader/IPC.hpp>
#include <Geode/loader/Log.hpp>
#include <loader/ModImpl.hpp>
#include <iostream>
#include <loader/LoaderImpl.hpp>
#include <Geode/utils/string.hpp>
using namespace geode::prelude;
#ifdef GEODE_IS_ANDROID
#include <android/log.h>
namespace {
android_LogPriority getLogSeverityForSeverity(Severity severity) {
switch (severity) {
case Severity::Debug: return ANDROID_LOG_DEBUG;
case Severity::Info: return ANDROID_LOG_INFO;
case Severity::Warning: return ANDROID_LOG_WARN;
case Severity::Error: return ANDROID_LOG_ERROR;
default: return ANDROID_LOG_DEFAULT;
}
}
}
void Loader::Impl::platformMessageBox(char const* title, std::string const& info) {
cocos2d::CCMessageBox(info.c_str(), title);
}
void Loader::Impl::logConsoleMessageWithSeverity(std::string const& msg, Severity severity) {
__android_log_print(
getLogSeverityForSeverity(severity),
"Geode",
"%s",
msg.c_str()
);
}
void Loader::Impl::openPlatformConsole() {
return;
}
void Loader::Impl::closePlatformConsole() {
return;
}
void Loader::Impl::setupIPC() {
log::warn("IPC is not supported on this platform!");
}
bool Loader::Impl::userTriedToLoadDLLs() const {
return false;
}
#endif

View file

@ -0,0 +1,36 @@
#include <Geode/DefaultInclude.hpp>
#ifdef GEODE_IS_ANDROID
#include <Geode/loader/Mod.hpp>
#include <loader/ModImpl.hpp>
using namespace geode::prelude;
Result<> Mod::Impl::loadPlatformBinary() {
auto so = dlopen((m_tempDirName / m_info.binaryName()).string().c_str(), RTLD_LAZY);
if (so) {
if (m_platformInfo) {
delete m_platformInfo;
}
m_platformInfo = new PlatformInfo{so};
return Ok();
}
std::string err = dlerror();
return Err("Unable to load the SO: dlerror returned (" + err + ")");
}
Result<> Mod::Impl::unloadPlatformBinary() {
auto so = m_platformInfo->m_so;
delete m_platformInfo;
m_platformInfo = nullptr;
if (dlclose(so) == 0) {
return Ok();
}
else {
return Err("Unable to free library");
}
}
#endif

View file

@ -0,0 +1,17 @@
#include <crashlog.hpp>
#ifdef GEODE_IS_ANDROID
ghc::filesystem::path crashlog::getCrashLogDirectory() {
return geode::dirs::getSaveDir();
}
bool crashlog::setupPlatformHandler() {
return false;
}
bool crashlog::didLastLaunchCrash() {
return false;
}
#endif

View file

@ -0,0 +1,33 @@
#include <Geode/DefaultInclude.hpp>
#ifdef GEODE_IS_ANDROID
using namespace geode::prelude;
#include <Geode/utils/cocos.hpp>
#include <Geode/loader/Dirs.hpp>
#include <Geode/utils/web.hpp>
#include <ghc/filesystem.hpp>
ghc::filesystem::path dirs::getGameDir() {
return ghc::filesystem::path(CCFileUtils::sharedFileUtils()->getWritablePath().c_str());
}
ghc::filesystem::path dirs::getSaveDir() {
return ghc::filesystem::path(CCFileUtils::sharedFileUtils()->getWritablePath().c_str());
}
void utils::web::openLinkInBrowser(std::string const& url) {
CCApplication::sharedApplication()->openURL(url.c_str());
}
bool utils::file::openFolder(ghc::filesystem::path const&) {
return false;
}
geode::Result<ghc::filesystem::path> utils::file::
pickFile(geode::utils::file::PickMode, geode::utils::file::FilePickOptions const&) {
return geode::Err("This function is currently unimplemented");
}
#endif