geode/loader/src/main.cpp

195 lines
6 KiB
C++
Raw Normal View History

2022-12-10 11:30:14 -05:00
#include "loader/LoaderImpl.hpp"
2022-10-30 14:56:36 -04:00
2022-12-03 07:24:31 -05:00
#include <Geode/loader/IPC.hpp>
2022-07-30 12:24:03 -04:00
#include <Geode/loader/Loader.hpp>
2022-10-30 14:56:36 -04:00
#include <Geode/loader/Log.hpp>
#include <Geode/loader/Mod.hpp>
2022-11-22 10:24:03 -05:00
#include <Geode/loader/Setting.hpp>
2022-12-03 07:24:31 -05:00
#include <Geode/loader/SettingEvent.hpp>
2023-01-14 18:00:59 -05:00
#include <Geode/loader/ModJsonTest.hpp>
#include <Geode/utils/JsonValidation.hpp>
#include <array>
2022-07-30 12:24:03 -04:00
2022-11-22 10:24:03 -05:00
USE_GEODE_NAMESPACE();
2022-07-30 12:24:03 -04:00
int geodeEntry(void* platformData);
// platform-specific entry points
#if defined(GEODE_IS_IOS) || defined(GEODE_IS_MACOS)
2022-10-30 14:56:36 -04:00
#include <dlfcn.h>
#include <mach-o/dyld.h>
#include <unistd.h>
2022-07-30 12:24:03 -04:00
std::length_error::~length_error() _NOEXCEPT {} // do not ask...
2022-10-30 14:56:36 -04:00
// camila has an old ass macos and this function turned
// from dynamic to static thats why she needs to define it
// this is what old versions does to a silly girl
2022-12-13 10:34:09 -05:00
void dynamicEntry() {
2022-10-08 05:59:06 -04:00
auto dylib = dlopen("GeodeBootstrapper.dylib", RTLD_NOLOAD);
dlclose(dylib);
std::array<char, PATH_MAX> gddir;
2022-07-30 12:24:03 -04:00
uint32_t out = PATH_MAX;
_NSGetExecutablePath(gddir.data(), &out);
2022-07-30 12:24:03 -04:00
ghc::filesystem::path gdpath = gddir.data();
2022-07-30 12:24:03 -04:00
ghc::filesystem::current_path(gdpath.parent_path().parent_path());
2022-10-08 06:21:57 -04:00
auto workingDir = gdpath.parent_path().parent_path();
auto libDir = workingDir / "Frameworks";
auto updatesDir = workingDir / "geode" / "update";
auto error = std::error_code();
if (ghc::filesystem::exists(updatesDir / "GeodeBootstrapper.dylib", error) && !error) {
ghc::filesystem::rename(
2022-10-30 14:56:36 -04:00
updatesDir / "GeodeBootstrapper.dylib", libDir / "GeodeBootstrapper.dylib", error
);
if (error) return;
}
2022-07-30 12:24:03 -04:00
geodeEntry(nullptr);
}
2022-12-13 10:34:09 -05:00
extern "C" __attribute__((visibility("default"))) void dynamicTrigger() {
std::thread(&dynamicEntry).detach();
}
// remove when we can figure out how to not remove it
auto dynamicTriggerRef = &dynamicTrigger;
2022-07-30 12:24:03 -04:00
#elif defined(GEODE_IS_WINDOWS)
2022-10-30 14:56:36 -04:00
#include <Windows.h>
2022-07-30 12:24:03 -04:00
DWORD WINAPI loadThread(void* arg) {
2022-10-11 15:03:16 -04:00
bool canMoveBootstrapper = true;
if (auto mod = GetModuleHandleA("GeodeBootstrapper.dll")) {
if (WaitForSingleObject(mod, 1000) != WAIT_OBJECT_0) {
canMoveBootstrapper = false;
}
}
2022-10-11 15:03:16 -04:00
if (canMoveBootstrapper) {
auto workingDir = ghc::filesystem::current_path();
auto updatesDir = workingDir / "geode" / "update";
2022-10-11 15:03:16 -04:00
auto error = std::error_code();
if (ghc::filesystem::exists(updatesDir / "GeodeBootstrapper.dll", error) && !error) {
ghc::filesystem::rename(
2022-10-30 14:56:36 -04:00
updatesDir / "GeodeBootstrapper.dll", workingDir / "GeodeBootstrapper.dll", error
2022-10-11 15:03:16 -04:00
);
if (error) return error.value();
}
}
2022-07-30 12:24:03 -04:00
return geodeEntry(arg);
}
BOOL WINAPI DllMain(HINSTANCE lib, DWORD reason, LPVOID) {
switch (reason) {
case DLL_PROCESS_ATTACH:
// Prevents threads from notifying this DLL on creation or destruction.
// Kind of redundant for a game that isn't multi-threaded but will provide
// some slight optimizations if a mod frequently creates and deletes threads.
DisableThreadLibraryCalls(lib);
// loading thread
HANDLE _ = CreateThread(0, 0, loadThread, lib, 0, nullptr);
if (_) CloseHandle(_);
break;
}
return TRUE;
}
#endif
$execute {
listenForSettingChanges("show-platform-console", +[](bool value) {
if (value) {
Loader::get()->openPlatformConsole();
2022-10-30 14:56:36 -04:00
}
else {
2022-12-10 11:30:14 -05:00
Loader::get()->closePlatformConsole();
}
2022-12-03 07:24:31 -05:00
});
listenForIPC("ipc-test", [](IPCEvent* event) -> json::Value {
return "Hello from Geode!";
});
2022-12-03 07:24:31 -05:00
listenForIPC("loader-info", [](IPCEvent* event) -> json::Value {
return Loader::get()->getModImpl()->getModInfo();
});
2022-12-03 07:24:31 -05:00
listenForIPC("list-mods", [](IPCEvent* event) -> json::Value {
std::vector<json::Value> res;
2022-12-03 07:24:31 -05:00
2023-01-14 18:00:59 -05:00
auto args = *event->messageData;
JsonChecker checker(args);
auto root = checker.root("").obj();
auto includeRunTimeInfo = root.has("include-runtime-info").template get<bool>();
auto dontIncludeLoader = root.has("dont-include-loader").template get<bool>();
if (!dontIncludeLoader) {
res.push_back(
includeRunTimeInfo ? Loader::get()->getModImpl()->getRuntimeInfo() :
Loader::get()->getModImpl()->getModInfo().toJSON()
);
}
2022-12-04 11:39:40 -05:00
for (auto& mod : Loader::get()->getAllMods()) {
res.push_back(includeRunTimeInfo ? mod->getRuntimeInfo() : mod->getModInfo().toJSON());
}
2022-12-04 11:39:40 -05:00
return res;
});
}
2022-07-30 12:24:03 -04:00
int geodeEntry(void* platformData) {
// set up internal mod, settings and data
2023-01-21 15:07:58 -05:00
auto internalSetupRes = LoaderImpl::get()->setupInternalMod();
if (!internalSetupRes) {
2023-01-21 11:56:01 -05:00
LoaderImpl::get()->platformMessageBox(
"Unable to Load Geode!",
"There was an unknown fatal error setting up "
2023-01-21 15:07:58 -05:00
"the internal mod and Geode can not be loaded." + internalSetupRes.unwrapErr()
);
LoaderImpl::get()->reset();
return 1;
}
2022-07-30 12:24:03 -04:00
// set up loader, load mods, etc.
2023-01-21 15:16:16 -05:00
auto setupRes = LoaderImpl::get()->setup();
if (!setupRes) {
2022-12-10 11:30:14 -05:00
LoaderImpl::get()->platformMessageBox(
2022-07-30 12:24:03 -04:00
"Unable to Load Geode!",
"There was an unknown fatal error setting up "
2023-01-21 15:16:16 -05:00
"the loader and Geode can not be loaded. "
"(" + setupRes.unwrapErr() + ")"
2022-07-30 12:24:03 -04:00
);
2022-12-10 11:30:14 -05:00
LoaderImpl::get()->reset();
2022-07-30 12:24:03 -04:00
return 1;
}
2022-10-08 10:05:53 -04:00
log::debug("Set up loader");
2022-10-30 14:56:36 -04:00
2023-01-24 05:00:19 -05:00
// open console
if (Mod::get()->getSettingValue<bool>("show-platform-console")) {
Loader::get()->openPlatformConsole();
}
2022-07-30 12:24:03 -04:00
2023-01-24 05:00:19 -05:00
// download and install new loader update in the background
if (Mod::get()->getSettingValue<bool>("auto-check-updates")) {
LoaderImpl::get()->checkForLoaderUpdates();
}
2022-10-08 10:05:53 -04:00
log::debug("Entry done.");
2022-10-06 17:09:15 -04:00
2022-07-30 12:24:03 -04:00
return 0;
}