diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/PojavLauncher.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/PojavLauncher.java index 00b20f6a..eab43f0b 100644 --- a/JavaApp/src/main/java/net/kdt/pojavlaunch/PojavLauncher.java +++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/PojavLauncher.java @@ -43,14 +43,13 @@ public class PojavLauncher { } }); - System.setProperty("cacio.managed.screensize", args[2]); try { // Try to initialize Caciocavallo17 Class.forName("com.github.caciocavallosilano.cacio.ctc.CTCPreloadClassLoader"); } catch (ClassNotFoundException e) {} - if (args[0].equals("--launchJar")) { - UIKit.callback_JavaGUIViewController_launchJarFile(args[1]); + if (args[0].equals("-jar")) { + UIKit.callback_JavaGUIViewController_launchJarFile(args[1], Arrays.copyOfRange(args, 2, args.length)); } else { launchMinecraft(args); } @@ -61,8 +60,9 @@ public class PojavLauncher { System.setProperty("appdir", "./spiral"); System.setProperty("resource_dir", "./spiral/rsrc"); - System.setProperty("glfw.windowSize", args[2]); - String[] size = args[2].split("x"); + String sizeStr = System.getProperty("cacio.managed.screensize"); + System.setProperty("glfw.windowSize", sizeStr); + String[] size = sizeStr.split("x"); MCOptionUtils.load(); MCOptionUtils.set("fullscreen", "false"); MCOptionUtils.set("overrideWidth", size[0]); diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java index 11e67deb..00883def 100644 --- a/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java +++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java @@ -29,45 +29,7 @@ public class UIKit { System.setProperty("os.name", osName); } - public static void callback_JavaGUIViewController_launchJarFile(final String filepath) throws Throwable { - // Thread for refreshing the AWT buffer - new Thread(() -> { - Method getCurrentScreenRGB; - try { - try { - getCurrentScreenRGB = Class.forName("net.java.openjdk.cacio.ctc.CTCScreen").getMethod("getCurrentScreenRGB"); - } catch (ClassNotFoundException e) { - getCurrentScreenRGB = Class.forName("com.github.caciocavallosilano.cacio.ctc.CTCScreen").getMethod("getCurrentScreenRGB"); - } - } catch (Throwable th) { - System.err.println("Failed to find class CTCScreen"); - th.printStackTrace(); - System.exit(1); - return; - } - - long lastTime = System.currentTimeMillis(); - while (true) { - int[] pixelsArray = null; - try{ - pixelsArray = (int[])getCurrentScreenRGB.invoke(null); - } catch (Throwable e) {} - if (pixelsArray != null) { - //System.out.println(java.util.Arrays.toString(pixelsArray)); - refreshAWTBuffer(pixelsArray); - } - long currentTime = System.currentTimeMillis(); - if (currentTime - lastTime < 16) { - try { - Thread.sleep(16 - (currentTime - lastTime)); - } catch (InterruptedException e) { - break; - } - } - lastTime = currentTime; - } - }, "AWTFBRefreshThread").start(); - + public static void callback_JavaGUIViewController_launchJarFile(final String filepath, String[] args) throws Throwable { // Launch the JAR file String mainClassName = null; @@ -78,15 +40,12 @@ public class UIKit { throw new IllegalArgumentException("no main manifest attribute, in \"" + filepath + "\""); } - PojavClassLoader loader = (PojavClassLoader) ClassLoader.getSystemClassLoader(); - loader.addURL(new File(filepath).toURI().toURL()); - // LabyMod Installer uses FlatLAF which has some macOS-specific codes, so we make it think it's running on Linux. patch_FlatLAF_setLinux(); - Class clazz = loader.loadClass(mainClass); + Class clazz = ClassLoader.getSystemClassLoader().loadClass(mainClass); Method method = clazz.getMethod("main", String[].class); - method.invoke(null, new Object[]{new String[]{}}); + method.invoke(null, new Object[]{args}); } public static void updateMCGuiScale() { diff --git a/Natives/JavaGUIViewController.m b/Natives/JavaGUIViewController.m index be32b27e..aa88ce31 100644 --- a/Natives/JavaGUIViewController.m +++ b/Natives/JavaGUIViewController.m @@ -13,43 +13,17 @@ #define SPECIALBTN_LOGOUTPUT -100 static BOOL shouldHitEnterAfterWindowShown; -static int* rgbArray; static SurfaceView* surfaceView; static jclass class_CTCAndroidInput; static jmethodID method_ReceiveInput; -JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_refreshAWTBuffer(JNIEnv* env, jclass clazz, jintArray jreRgbArray) { - if (!runtimeJNIEnvPtr) { - dispatch_async(dispatch_get_main_queue(), ^{ - (*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, &runtimeJNIEnvPtr, NULL); - assert(runtimeJNIEnvPtr); - }); - } - - int *tmpArray = (*env)->GetIntArrayElements(env, jreRgbArray, 0); - memcpy(rgbArray, tmpArray, windowWidth * windowHeight * 4); - (*env)->ReleaseIntArrayElements(env, jreRgbArray, tmpArray, JNI_ABORT); - dispatch_async(dispatch_get_main_queue(), ^{ - [surfaceView displayLayer]; - }); - - // Wait until something renders at the middle - if (shouldHitEnterAfterWindowShown && rgbArray[windowWidth/2 + windowWidth*windowHeight/2] != 0) { - shouldHitEnterAfterWindowShown = NO; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 200 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^(void){ - // Auto hit Enter to install immediately - AWTInputBridge_sendKey('\n'); - }); - } -} - void AWTInputBridge_nativeSendData(int type, int i1, int i2, int i3, int i4) { - if (runtimeJNIEnvPtr == NULL) { + if (!runtimeJNIEnvPtr) { return; } - if (method_ReceiveInput == NULL) { + if (!method_ReceiveInput) { class_CTCAndroidInput = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "net/java/openjdk/cacio/ctc/CTCAndroidInput"); if ((*runtimeJNIEnvPtr)->ExceptionCheck(runtimeJNIEnvPtr) == JNI_TRUE) { (*runtimeJNIEnvPtr)->ExceptionClear(runtimeJNIEnvPtr); @@ -78,11 +52,66 @@ void AWTInputBridge_sendKey(int keycode) { AWTInputBridge_nativeSendData(EVENT_TYPE_KEY, ' ', keycode, 0, 0); } -@interface SurfaceView() +@interface SurfaceView() { + JNIEnv *surfaceJNIEnv; + jclass class_CTCScreen; + jmethodID method_GetRGB; + int *rgbArray; +} @property(nonatomic) CGColorSpaceRef colorSpace; @end @implementation SurfaceView +- (void)refreshBuffer { + if (!runtimeJavaVMPtr) { + // JVM is not ready yet + return; + } else if (!surfaceJNIEnv) { + // Obtain JNIEnvs + (*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, &surfaceJNIEnv, NULL); + assert(surfaceJNIEnv); + dispatch_async(dispatch_get_main_queue(), ^{ + (*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, &runtimeJNIEnvPtr, NULL); + assert(runtimeJNIEnvPtr); + }); + + // Obtain CTCScreen.getCurrentScreenRGB() + class_CTCScreen = (*surfaceJNIEnv)->FindClass(surfaceJNIEnv, "net/java/openjdk/cacio/ctc/CTCScreen"); + if ((*surfaceJNIEnv)->ExceptionCheck(surfaceJNIEnv) == JNI_TRUE) { + (*surfaceJNIEnv)->ExceptionClear(surfaceJNIEnv); + class_CTCScreen = (*surfaceJNIEnv)->FindClass(surfaceJNIEnv, "com/github/caciocavallosilano/cacio/ctc/CTCScreen"); + } + assert(class_CTCScreen != NULL); + method_GetRGB = (*surfaceJNIEnv)->GetStaticMethodID(surfaceJNIEnv, class_CTCScreen, "getCurrentScreenRGB", "()[I"); + assert(method_GetRGB != NULL); + rgbArray = calloc(4, (size_t) (windowWidth * windowHeight)); + } + + jintArray jreRgbArray = (jintArray) (*surfaceJNIEnv)->CallStaticObjectMethod( + surfaceJNIEnv, + class_CTCScreen, + method_GetRGB + ); + if (!jreRgbArray) { + return; + } + int *tmpArray = (*surfaceJNIEnv)->GetIntArrayElements(surfaceJNIEnv, jreRgbArray, 0); + memcpy(rgbArray, tmpArray, windowWidth * windowHeight * 4); + (*surfaceJNIEnv)->ReleaseIntArrayElements(surfaceJNIEnv, jreRgbArray, tmpArray, JNI_ABORT); + dispatch_async(dispatch_get_main_queue(), ^{ + [surfaceView displayLayer]; + }); + + // Wait until something renders at the middle + if (shouldHitEnterAfterWindowShown && rgbArray[windowWidth/2 + windowWidth*windowHeight/2] != 0) { + shouldHitEnterAfterWindowShown = NO; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 200 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^(void){ + // Auto hit Enter to install immediately + AWTInputBridge_sendKey('\n'); + }); + } +} + - (void)displayLayer { CGDataProviderRef bitmapProvider = CGDataProviderCreateWithData(NULL, rgbArray, windowWidth * windowHeight * 4, NULL); CGImageRef bitmap = CGImageCreate(windowWidth, windowHeight, 8, 32, 4 * windowWidth, _colorSpace, kCGImageAlphaFirst | kCGBitmapByteOrder32Little, bitmapProvider, NULL, FALSE, kCGRenderingIntentDefault); @@ -266,9 +295,21 @@ void AWTInputBridge_sendKey(int keycode) { self.logOutputView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; [self.view addSubview:self.logOutputView]; - rgbArray = calloc(4, (size_t) (windowWidth * windowHeight)); - setenv("POJAV_SKIP_JNI_GLFW", "1", 1); + + // Register the display loop + CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:surfaceView selector:@selector(refreshBuffer)]; + if (@available(iOS 15.0, tvOS 15.0, *)) { + if(getPrefBool(@"video.max_framerate")) { + displayLink.preferredFrameRateRange = CAFrameRateRangeMake(30, 120, 120); + } else { + displayLink.preferredFrameRateRange = CAFrameRateRangeMake(30, 60, 60); + } + } + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [displayLink addToRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes]; + }); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ launchJVM(nil, self.filepath, windowWidth, windowHeight, _requiredJavaVersion); @@ -373,8 +414,6 @@ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ } - (void)showErrorMessage:(NSString *)message { - free(rgbArray); - rgbArray = NULL; surfaceView = nil; showDialog(localize(@"Error", nil), message); } diff --git a/Natives/JavaLauncher.m b/Natives/JavaLauncher.m index 20071afd..64ec79fa 100644 --- a/Natives/JavaLauncher.m +++ b/Natives/JavaLauncher.m @@ -94,8 +94,8 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi init_loadDefaultEnv(); init_loadCustomEnv(); + BOOL launchJar = NO; NSString *gameDir; - NSString *defaultJRETag; if ([launchTarget isKindOfClass:NSDictionary.class]) { // Get preferred Java version from current profile @@ -126,6 +126,7 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi } else { defaultJRETag = @"execute_jar"; gameDir = @(getenv("POJAV_GAME_DIR")); + launchJar = YES; } NSLog(@"[JavaLauncher] Looking for Java %d or later", minVersion); NSString *javaHome = getSelectedJavaHome(defaultJRETag, minVersion); @@ -171,7 +172,9 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi margv[++margc] = [NSString stringWithFormat:@"%@/bin/java", javaHome].UTF8String; margv[++margc] = "-XstartOnFirstThread"; - margv[++margc] = "-Djava.system.class.loader=net.kdt.pojavlaunch.PojavClassLoader"; + if (!launchJar) { + margv[++margc] = "-Djava.system.class.loader=net.kdt.pojavlaunch.PojavClassLoader"; + } margv[++margc] = "-Xms128M"; margv[++margc] = [NSString stringWithFormat:@"-Xmx%dM", allocmem].UTF8String; margv[++margc] = [NSString stringWithFormat:@"-Djava.library.path=%@/Frameworks", NSBundle.mainBundle.bundlePath].UTF8String; @@ -204,11 +207,6 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi margv[++margc] = "-XX:+UnlockExperimentalVMOptions"; margv[++margc] = "-XX:+DisablePrimordialThreadGuardPages"; - // Setup Caciocavallo - margv[++margc] = "-Djava.awt.headless=false"; - margv[++margc] = "-Dcacio.font.fontmanager=sun.awt.X11FontManager"; - margv[++margc] = "-Dcacio.font.fontscaler=sun.font.FreetypeFontScaler"; - // Disable Forge 1.16.x early progress window margv[++margc] = "-Dfml.earlyprogresswindow=false"; @@ -227,9 +225,14 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi return 1; } + // Setup Caciocavallo + margv[++margc] = "-Djava.awt.headless=false"; + margv[++margc] = "-Dcacio.font.fontmanager=sun.awt.X11FontManager"; + margv[++margc] = "-Dcacio.font.fontscaler=sun.font.FreetypeFontScaler"; + margv[++margc] = [NSString stringWithFormat:@"-Dcacio.managed.screensize=%dx%d", width, height].UTF8String; + margv[++margc] = "-Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel"; if (isJava8) { // Setup Caciocavallo - margv[++margc] = "-Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel"; margv[++margc] = "-Dawt.toolkit=net.java.openjdk.cacio.ctc.CTCToolkit"; margv[++margc] = "-Djava.awt.graphicsenv=net.java.openjdk.cacio.ctc.CTCGraphicsEnvironment"; } else { @@ -237,7 +240,6 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi margv[++margc] = "--add-opens=java.base/java.net=ALL-UNNAMED"; // Setup Caciocavallo - margv[++margc] = "-Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel"; margv[++margc] = "-Dawt.toolkit=com.github.caciocavallosilano.cacio.ctc.CTCToolkit"; margv[++margc] = "-Djava.awt.graphicsenv=com.github.caciocavallosilano.cacio.ctc.CTCGraphicsEnvironment"; @@ -289,21 +291,26 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi init_loadCustomJvmFlags(&margc, (const char **)margv); NSLog(@"[Init] Found JLI lib"); + NSString *classpath = [NSString stringWithFormat:@"%@/*", librariesPath]; + if (launchJar) { + classpath = [classpath stringByAppendingFormat:@":%@", launchTarget]; + } margv[++margc] = "-cp"; - margv[++margc] = [NSString stringWithFormat:@"%@/*", librariesPath].UTF8String; + margv[++margc] = classpath.UTF8String; margv[++margc] = "net.kdt.pojavlaunch.PojavLauncher"; - if (username == nil) { - margv[++margc] = "--launchJar"; + if (launchJar) { + margv[++margc] = "-jar"; } else { margv[++margc] = username.UTF8String; } + if ([launchTarget isKindOfClass:NSDictionary.class]) { margv[++margc] = [launchTarget[@"id"] UTF8String]; } else { margv[++margc] = [launchTarget UTF8String]; } - margv[++margc] = [NSString stringWithFormat:@"%dx%d", width, height].UTF8String; + //margv[++margc] = "ghidra.GhidraRun"; pJLI_Launch = (JLI_Launch_func *)dlsym(libjli, "JLI_Launch"); diff --git a/Natives/PLLogOutputView.m b/Natives/PLLogOutputView.m index 8bfe3315..4275a31d 100644 --- a/Natives/PLLogOutputView.m +++ b/Natives/PLLogOutputView.m @@ -173,6 +173,7 @@ static PLLogOutputView* current; } + (void)handleExitCode:(int)code { + if (!current) return; dispatch_async(dispatch_get_main_queue(), ^(void){ if (current.hidden) { [current actionToggleLogOutput]; diff --git a/Natives/input_bridge_v3.m b/Natives/input_bridge_v3.m index c55c4c9c..caf454fa 100644 --- a/Natives/input_bridge_v3.m +++ b/Natives/input_bridge_v3.m @@ -102,7 +102,7 @@ hooked_ProcessImpl_forkAndExec(JNIEnv *env, jobject process, jint mode, jbyteArr jlong hooked_ProcessHandleImpl_isAlive0(JNIEnv *env, jclass clazz, jlong jpid) { jlong result = orig_ProcessHandleImpl_isAlive0(env, clazz, jpid); if ((*env)->ExceptionOccurred(env)) { - (*env)->ExceptionClear(runtimeJNIEnvPtr); + (*env)->ExceptionClear(env); } return result; } @@ -137,61 +137,61 @@ void CTCDesktopPeer_openGlobal(JNIEnv *env, jclass clazz, jstring path) { (*env)->ReleaseStringUTFChars(env, path, stringChars); } -void registerOpenHandler() { +void registerOpenHandler(JNIEnv *env) { jclass cls; // Hook forkAndExec orig_ProcessImpl_forkAndExec = dlsym(RTLD_DEFAULT, "Java_java_lang_UNIXProcess_forkAndExec"); if (!orig_ProcessImpl_forkAndExec) { orig_ProcessImpl_forkAndExec = dlsym(RTLD_DEFAULT, "Java_java_lang_ProcessImpl_forkAndExec"); - cls = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "java/lang/ProcessImpl"); + cls = (*env)->FindClass(env, "java/lang/ProcessImpl"); } else { - cls = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "java/lang/UNIXProcess"); + cls = (*env)->FindClass(env, "java/lang/UNIXProcess"); } JNINativeMethod forkAndExecMethod[] = { {"forkAndExec", "(I[B[B[BI[BI[B[IZ)I", (void *)&hooked_ProcessImpl_forkAndExec} }; - (*runtimeJNIEnvPtr)->RegisterNatives(runtimeJNIEnvPtr, cls, forkAndExecMethod, 1); + (*env)->RegisterNatives(env, cls, forkAndExecMethod, 1); // (Java 17 only) Hook isAlive0 - cls = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "java/lang/ProcessHandleImpl"); - if ((*runtimeJNIEnvPtr)->ExceptionOccurred(runtimeJNIEnvPtr)) { + cls = (*env)->FindClass(env, "java/lang/ProcessHandleImpl"); + if ((*env)->ExceptionOccurred(env)) { // Java 8 - (*runtimeJNIEnvPtr)->ExceptionClear(runtimeJNIEnvPtr); + (*env)->ExceptionClear(env); } else { orig_ProcessHandleImpl_isAlive0 = dlsym(RTLD_DEFAULT, "Java_java_lang_ProcessHandleImpl_isAlive0"); JNINativeMethod isAlive0Method[] = { {"isAlive0", "(J)J", (void *)&hooked_ProcessHandleImpl_isAlive0} }; - (*runtimeJNIEnvPtr)->RegisterNatives(runtimeJNIEnvPtr, cls, isAlive0Method, 1); + (*env)->RegisterNatives(env, cls, isAlive0Method, 1); } // Register CTCClipboard natives - cls = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "net/java/openjdk/cacio/ctc/CTCClipboard"); - if ((*runtimeJNIEnvPtr)->ExceptionOccurred(runtimeJNIEnvPtr)) { + cls = (*env)->FindClass(env, "net/java/openjdk/cacio/ctc/CTCClipboard"); + if ((*env)->ExceptionOccurred(env)) { // Java 17 - (*runtimeJNIEnvPtr)->ExceptionClear(runtimeJNIEnvPtr); - cls = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "com/github/caciocavallosilano/cacio/ctc/CTCClipboard"); + (*env)->ExceptionClear(env); + cls = (*env)->FindClass(env, "com/github/caciocavallosilano/cacio/ctc/CTCClipboard"); } JNINativeMethod clipboardMethods[] = { {"nQuerySystemClipboard", "()V", (void *)&CTCClipboard_nQuerySystemClipboard}, {"nPutClipboardData", "(Ljava/lang/String;Ljava/lang/String;)V", (void *)&CTCClipboard_nPutClipboardData} }; - (*runtimeJNIEnvPtr)->RegisterNatives(runtimeJNIEnvPtr, cls, clipboardMethods, 2); + (*env)->RegisterNatives(env, cls, clipboardMethods, 2); // Register CTCDesktopPeer natives - cls = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "net/java/openjdk/cacio/ctc/CTCDesktopPeer"); - if ((*runtimeJNIEnvPtr)->ExceptionOccurred(runtimeJNIEnvPtr)) { + cls = (*env)->FindClass(env, "net/java/openjdk/cacio/ctc/CTCDesktopPeer"); + if ((*env)->ExceptionOccurred(env)) { // Java 17, not available - //(*runtimeJNIEnvPtr)->ExceptionDescribe(runtimeJNIEnvPtr); - (*runtimeJNIEnvPtr)->ExceptionClear(runtimeJNIEnvPtr); + //(*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); return; } JNINativeMethod peerOpenMethods[] = { {"openFile", "(Ljava/lang/String;)V", (void *)&CTCDesktopPeer_openGlobal}, {"openUri", "(Ljava/lang/String;)V", (void *)&CTCDesktopPeer_openGlobal} }; - (*runtimeJNIEnvPtr)->RegisterNatives(runtimeJNIEnvPtr, cls, peerOpenMethods, 2); + (*env)->RegisterNatives(env, cls, peerOpenMethods, 2); } // JNI_OnLoad @@ -206,11 +206,11 @@ void JNI_OnLoadGLFW() { jint JNI_OnLoad(JavaVM* vm, void* reserved) { runtimeJavaVMPtr = vm; - (*runtimeJavaVMPtr)->GetEnv(runtimeJavaVMPtr, (void **)&runtimeJNIEnvPtr, JNI_VERSION_1_4); - registerOpenHandler(); - if (getenv("POJAV_SKIP_JNI_GLFW")) { - runtimeJNIEnvPtr = nil; - } else { + JNIEnv *env; + (*runtimeJavaVMPtr)->GetEnv(runtimeJavaVMPtr, (void **)&env, JNI_VERSION_1_4); + registerOpenHandler(env); + if (!getenv("POJAV_SKIP_JNI_GLFW")) { + runtimeJNIEnvPtr = env; JNI_OnLoadGLFW(); } diff --git a/Natives/main_hook.m b/Natives/main_hook.m index d92d407d..0d87adae 100644 --- a/Natives/main_hook.m +++ b/Natives/main_hook.m @@ -11,7 +11,7 @@ void (*orig_exit)(int code); int (*orig_open)(const char *path, int oflag, ...); void handle_fatal_exit(int code) { - if (NSThread.isMainThread || !SurfaceViewController.isRunning) { + if (NSThread.isMainThread) { return; }