|
| 1 | +#include <codegen/il2cpp-codegen-metadata.h> |
| 2 | +#include <utils/Exception.h> |
| 3 | +#include <os/Image.h> |
| 4 | +#include <Cpp/Baselib_DynamicLibrary.h> |
| 5 | +#include <fcontext.h> |
| 6 | + |
| 7 | +extern "C" char *GC_approx_sp(void); |
| 8 | +extern "C" char *GC_get_main_stack_base(void); |
| 9 | +extern "C" char *GC_stackbottom; |
| 10 | +typedef void (* GC_push_other_roots_proc)(void); |
| 11 | +extern "C" void GC_set_push_other_roots(GC_push_other_roots_proc); |
| 12 | +extern "C" GC_push_other_roots_proc GC_get_push_other_roots(void); |
| 13 | +extern "C" void GC_push_all_stack_sections(char *lo, char *hi, void *); |
| 14 | +typedef void *(* GC_fn_type)(void *); |
| 15 | +extern "C" void *GC_call_with_alloc_lock(GC_fn_type fn, void *client_data); |
| 16 | + |
| 17 | +typedef struct uv_loop_s { void* data; } uv_loop_t; |
| 18 | +typedef struct uv_idle_s { void* data; uv_loop_t* loop; } uv_idle_t; |
| 19 | +typedef void (*uv_idle_cb)(uv_idle_t* handle); |
| 20 | +static int (*uv_idle_init)(uv_loop_t*, uv_idle_t* idle); |
| 21 | +static int (*uv_idle_start)(uv_idle_t* idle, uv_idle_cb cb); |
| 22 | + |
| 23 | +typedef struct napi_env__* napi_env; |
| 24 | +typedef enum { napi_ok } napi_status; |
| 25 | +static napi_status (*napi_get_uv_event_loop)(napi_env env, struct uv_loop_s** loop); |
| 26 | + |
| 27 | +using namespace il2cpp; |
| 28 | + |
| 29 | +extern "C" void UnityFiberProc() |
| 30 | +{ |
| 31 | + std::string imagePath = os::Image::GetImageName(); |
| 32 | + imagePath = imagePath.substr(0, imagePath.find_last_of(IL2CPP_DIR_SEPARATOR)); |
| 33 | +#if defined(__APPLE__) |
| 34 | + imagePath += "/UnityPlayer.dylib"; |
| 35 | +#elif defined(_WIN32) |
| 36 | + imagePath += "\\UnityPlayer.dll"; |
| 37 | +#endif |
| 38 | + |
| 39 | + auto errorState = Baselib_ErrorState_Create(); |
| 40 | + auto playerLib = Baselib_DynamicLibrary_Open(imagePath.c_str(), &errorState); |
| 41 | + if (Baselib_ErrorState_ErrorRaised(&errorState)) |
| 42 | + { |
| 43 | + printf("error: %s\n", utils::Exception::FormatBaselibErrorState(errorState).c_str()); |
| 44 | + abort(); |
| 45 | + } |
| 46 | + |
| 47 | +#if defined(__APPLE__) |
| 48 | + extern int PlayerMain(int argc, const char *argv[]); |
| 49 | + auto playerProc = (decltype(&PlayerMain))Baselib_DynamicLibrary_GetFunction(playerLib, "_Z10PlayerMainiPPKc", &errorState); |
| 50 | +#elif defined(_WIN32) |
| 51 | + extern int UnityMain2(void *hInstance, const wchar_t *customDataFolder, wchar_t *lpCmdLine, int nShowCmd); |
| 52 | + auto playerProc = (decltype(&UnityMain2))Baselib_DynamicLibrary_GetFunction(playerLib, "UnityMain2", &errorState); |
| 53 | +#endif |
| 54 | + |
| 55 | + if (!playerProc) |
| 56 | + { |
| 57 | + printf("error: %s\n", utils::Exception::FormatBaselibErrorState(errorState).c_str()); |
| 58 | + abort(); |
| 59 | + } |
| 60 | + |
| 61 | +#if defined(__APPLE__) |
| 62 | + imagePath = imagePath.substr(0, imagePath.find_last_of(IL2CPP_DIR_SEPARATOR)); |
| 63 | + imagePath = imagePath.substr(0, imagePath.find_last_of(IL2CPP_DIR_SEPARATOR)); |
| 64 | + imagePath = imagePath.substr(0, imagePath.find_last_of(IL2CPP_DIR_SEPARATOR)); |
| 65 | + extern void NSBundle_fixup(const char *path); |
| 66 | + NSBundle_fixup(imagePath.c_str()); |
| 67 | + |
| 68 | + const char *argv[] = { os::Image::GetImageName(), "-logfile", "-" }; |
| 69 | + playerProc(1, argv); |
| 70 | +#elif defined(_WIN32) |
| 71 | + imagePath = imagePath.substr(0, imagePath.find_last_of(IL2CPP_DIR_SEPARATOR)); |
| 72 | + imagePath += "\\unode-module_Data"; |
| 73 | + auto dataPath = utils::StringUtils::Utf8ToNativeString(imagePath); |
| 74 | + |
| 75 | + extern IMPORTED_SYMBOL int SetProcessDpiAwarenessContext(int); |
| 76 | + SetProcessDpiAwarenessContext(-4); |
| 77 | + |
| 78 | + extern IMPORTED_SYMBOL void *GetModuleHandleW(wchar_t *); |
| 79 | + playerProc(GetModuleHandleW(nullptr), dataPath.c_str(), L"-logfile -", 5); |
| 80 | +#endif |
| 81 | + |
| 82 | + Baselib_DynamicLibrary_Close(playerLib); |
| 83 | +} |
| 84 | + |
| 85 | +static char *GC_stackbottom_alt; |
| 86 | +static char *GC_stacktop_alt; |
| 87 | + |
| 88 | +static const auto GC_push_other_roots = GC_get_push_other_roots(); |
| 89 | +static void MY_push_other_roots(void) |
| 90 | +{ |
| 91 | + GC_push_all_stack_sections(GC_stacktop_alt, GC_stackbottom_alt, nullptr); |
| 92 | + GC_push_other_roots(); |
| 93 | +} |
| 94 | + |
| 95 | +static fcontext_t MY_fiber; |
| 96 | +static fcontext_t MY_fiber_alt; |
| 97 | + |
| 98 | +static IL2CPP_NO_INLINE void node_jump(uv_idle_t *context) |
| 99 | +{ |
| 100 | + auto ctx = (fcontext_t *)GC_call_with_alloc_lock([](void *context) -> void * |
| 101 | + { |
| 102 | + auto GC_stacktop = GC_approx_sp(); |
| 103 | + std::swap(GC_stacktop, GC_stacktop_alt); |
| 104 | + std::swap(GC_stackbottom, GC_stackbottom_alt); |
| 105 | + std::swap(MY_fiber, MY_fiber_alt); |
| 106 | + return jump_fcontext(MY_fiber, nullptr).ctx; |
| 107 | + }, nullptr); |
| 108 | + |
| 109 | + if (MY_fiber_alt) |
| 110 | + MY_fiber_alt = ctx; |
| 111 | +} |
| 112 | + |
| 113 | +extern "C" EXPORTED_SYMBOL void *napi_register_module_v1(napi_env env, void *exports) |
| 114 | +{ |
| 115 | + fcontext_stack_t s = create_fcontext_stack(1024 * 1024); |
| 116 | + MY_fiber_alt = make_fcontext(s.sptr, s.ssize, [](fcontext_transfer_t t) |
| 117 | + { |
| 118 | + MY_fiber_alt = t.ctx; |
| 119 | + UnityFiberProc(); |
| 120 | + MY_fiber = nullptr; |
| 121 | + node_jump({}); |
| 122 | + }); |
| 123 | + |
| 124 | + GC_stackbottom_alt = (char *)s.sptr; |
| 125 | + GC_stackbottom = GC_get_main_stack_base(); |
| 126 | + GC_set_push_other_roots(MY_push_other_roots); |
| 127 | + |
| 128 | + extern void display_link(void (*cb)(uv_idle_t *), uv_idle_t *data); |
| 129 | + display_link(&node_jump, nullptr); |
| 130 | + |
| 131 | + atexit([]{ quick_exit(0); }); |
| 132 | + node_jump({}); |
| 133 | + |
| 134 | + auto errorState = Baselib_ErrorState_Create(); |
| 135 | + auto progHandle = Baselib_DynamicLibrary_OpenProgramHandle(&errorState); |
| 136 | + napi_get_uv_event_loop = (decltype(napi_get_uv_event_loop))Baselib_DynamicLibrary_GetFunction(progHandle, "napi_get_uv_event_loop", &errorState); |
| 137 | + uv_idle_init = (decltype(uv_idle_init))Baselib_DynamicLibrary_GetFunction(progHandle, "uv_idle_init", &errorState); |
| 138 | + uv_idle_start = (decltype(uv_idle_start))Baselib_DynamicLibrary_GetFunction(progHandle, "uv_idle_start", &errorState); |
| 139 | + if (Baselib_ErrorState_ErrorRaised(&errorState)) |
| 140 | + { |
| 141 | + printf("error: %s\n", utils::Exception::FormatBaselibErrorState(errorState).c_str()); |
| 142 | + return nullptr; |
| 143 | + } |
| 144 | + Baselib_DynamicLibrary_Close(progHandle); |
| 145 | + |
| 146 | + uv_loop_t *loop; |
| 147 | + napi_get_uv_event_loop(env, &loop); |
| 148 | + |
| 149 | + static uv_idle_t idler; |
| 150 | + uv_idle_init(loop, &idler); |
| 151 | + uv_idle_start(&idler, &node_jump); |
| 152 | + |
| 153 | + extern const Il2CppMethodPointer g_ReversePInvokeWrapperPointers[]; |
| 154 | + extern const Il2CppCodeGenModule g_Unity_NodeApi_CodeGenModule; |
| 155 | + |
| 156 | + auto func = g_ReversePInvokeWrapperPointers[g_Unity_NodeApi_CodeGenModule.reversePInvokeWrapperIndices[0].index]; |
| 157 | + return reinterpret_cast<decltype(&napi_register_module_v1)>(func)(env, exports); |
| 158 | +} |
0 commit comments