diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/PLaunchApp.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/PLaunchApp.java
index c397bc80..bdca3177 100644
--- a/JavaApp/src/main/java/net/kdt/pojavlaunch/PLaunchApp.java
+++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/PLaunchApp.java
@@ -5,13 +5,14 @@ import java.util.*;
import java.util.concurrent.*;
import org.lwjgl.glfw.CallbackBridge;
+import org.lwjgl.glfw.GLFW;
import net.kdt.pojavlaunch.uikit.*;
import net.kdt.pojavlaunch.utils.*;
import net.kdt.pojavlaunch.value.*;
public class PLaunchApp {
- private static float currProgress, maxProgress;
+ private static float currProgress, maxProgress;
public static void main(String[] args) throws Throwable {
try {
@@ -20,57 +21,56 @@ public class PLaunchApp {
// Not on JRE8, ignore exception
}
- // User might remove the minecraft folder, this can cause crashes, safety re-create it
- try {
- File mcDir = new File(Tools.DIR_GAME_NEW);
- mcDir.mkdirs();
- new File(Tools.DIR_ACCOUNT_NEW).mkdirs();
- if (!new File(mcDir.getAbsolutePath() + "/launcher_profiles.json").exists()) {
- Tools.write(mcDir.getAbsolutePath() + "/launcher_profiles.json",
- Tools.read(Tools.DIR_BUNDLE + "/launcher_profiles.json"));
+ Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+
+ public void uncaughtException(Thread t, Throwable th) {
+ Tools.showError(th);
+ // Block this thread from exiting
+ while (true) {}
}
- } catch (IOException e) {
- e.printStackTrace();
- }
+ });
- System.out.println("We are on java now! Starting UI...");
- UIKit.launchUI();
- }
+ System.setProperty("cacio.managed.screensize", args[2]);
- public static String getStringFromPref(String pref) {
- try {
- String plistContent = Tools.read(Tools.DIR_APP_DATA + "/launcher_preferences.plist");
- plistContent = plistContent.substring(plistContent.indexOf("" + pref + "") + pref.length() + 11);
- return plistContent.substring(
- plistContent.indexOf("") + 8,
- plistContent.indexOf(""));
- } catch (IOException e) {
- e.printStackTrace();
- return null;
+ if (args[0].equals(".LaunchJAR")) {
+ UIKit.callback_JavaGUIViewController_launchJarFile(args[1]);
+ } else {
+ launchMinecraft(args);
}
}
- // Called from SurfaceViewController
- public static void launchMinecraft() {
- try {
- MinecraftAccount account = MinecraftAccount.load(getStringFromPref("internal_selected_account"));
- JMinecraftVersionList.Version version = Tools.getVersionInfo(getStringFromPref("selected_version"));
- System.out.println("Launching Minecraft " + version.id);
- String configPath;
- if (version.logging != null) {
- if (version.logging.client.file.id.equals("client-1.12.xml")) {
- configPath = Tools.DIR_BUNDLE + "/log4j-rce-patch-1.12.xml";
- } else if (version.logging.client.file.id.equals("client-1.7.xml")) {
- configPath = Tools.DIR_BUNDLE + "/log4j-rce-patch-1.7.xml";
- } else {
- configPath = Tools.DIR_GAME_NEW + "/" + version.logging.client.file.id;
- }
- System.setProperty("log4j.configurationFile", configPath);
+ public static void launchMinecraft(String[] args) throws Throwable {
+ String[] size = args[2].split("x");
+
+ MCOptionUtils.load();
+ MCOptionUtils.set("overrideWidth", size[0]);
+ MCOptionUtils.set("overrideHeight", size[1]);
+ MCOptionUtils.save();
+
+ System.setProperty("org.lwjgl.opengl.libname", System.getenv("POJAV_RENDERER"));
+
+ Tools.mGLFWWindowWidth = Integer.parseInt(size[0]);
+ Tools.mGLFWWindowHeight = Integer.parseInt(size[1]);
+ //GLFW.internalChangeMonitorSize(width, height);
+ //CallbackBridge.mouseX = width / 2;
+ //CallbackBridge.mouseY = height / 2;
+
+ MinecraftAccount account = MinecraftAccount.load(args[0]);
+ JMinecraftVersionList.Version version = Tools.getVersionInfo(args[1]);
+ System.out.println("Launching Minecraft " + version.id);
+ String configPath;
+ if (version.logging != null) {
+ if (version.logging.client.file.id.equals("client-1.12.xml")) {
+ configPath = Tools.DIR_BUNDLE + "/log4j-rce-patch-1.12.xml";
+ } else if (version.logging.client.file.id.equals("client-1.7.xml")) {
+ configPath = Tools.DIR_BUNDLE + "/log4j-rce-patch-1.7.xml";
+ } else {
+ configPath = Tools.DIR_GAME_NEW + "/" + version.logging.client.file.id;
}
- Tools.launchMinecraft(account, version);
- } catch (Throwable th) {
- Tools.showError(th);
+ System.setProperty("log4j.configurationFile", configPath);
}
+
+ Tools.launchMinecraft(account, version);
}
// TODO
diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/Tools.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/Tools.java
index 2656ec5f..401859ab 100644
--- a/JavaApp/src/main/java/net/kdt/pojavlaunch/Tools.java
+++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/Tools.java
@@ -37,12 +37,7 @@ import net.kdt.pojavlaunch.utils.JSONUtils;
import net.kdt.pojavlaunch.value.DependentLibrary;
import net.kdt.pojavlaunch.value.MinecraftAccount;
import org.lwjgl.glfw.GLFW;
-/*
-import org.robovm.apple.foundation.*;
-import org.robovm.apple.uikit.*;
-import org.robovm.pods.dialog.*;
-import org.robovm.pods.*;
-*/
+
public final class Tools
{
public static final boolean ENABLE_DEV_FEATURES = true; // BuildConfig.DEBUG;
@@ -78,6 +73,8 @@ public final class Tools
public static final String LIBNAME_OPTIFINE = "optifine:OptiFine";
+ volatile public static int mGLFWWindowWidth, mGLFWWindowHeight;
+
public static void launchMinecraft(MinecraftAccount profile, final JMinecraftVersionList.Version versionInfo) throws Throwable {
String javaVersion = System.getProperty("java.version");
if (javaVersion.startsWith("1.")) {
@@ -125,31 +122,27 @@ public final class Tools
}
}
*/
-
- new Thread(() -> { try {
- System.out.println("Args init finished. Now starting game");
-
- // URLClassLoader loader = new URLClassLoader(urlList.toArray(new URL[0]), ClassLoader.getSystemClassLoader());
-
- PojavClassLoader loader = (PojavClassLoader) ClassLoader.getSystemClassLoader();
- // add launcher.jar itself
- loader.addURL(Tools.class.getProtectionDomain().getCodeSource().getLocation().toURI().toURL());
- for (String s : launchClassPath.split(":")) {
- if (!s.isEmpty()) {
- loader.addURL(new File(s).toURI().toURL());
- }
- }
-
- Class> clazz = loader.loadClass(versionInfo.mainClass);
- Method method = clazz.getMethod("main", String[].class);
- method.invoke(null, new Object[]{launchArgs});
- // throw new RuntimeException("Game exited. Check latestlog.txt for more details.");
- } catch (Throwable th) {
- showError(th);
+ System.out.println("Args init finished. Now starting game");
+
+ // URLClassLoader loader = new URLClassLoader(urlList.toArray(new URL[0]), ClassLoader.getSystemClassLoader());
+
+ PojavClassLoader loader = (PojavClassLoader) ClassLoader.getSystemClassLoader();
+ // add launcher.jar itself
+ loader.addURL(Tools.class.getProtectionDomain().getCodeSource().getLocation().toURI().toURL());
+ for (String s : launchClassPath.split(":")) {
+ if (!s.isEmpty()) {
+ loader.addURL(new File(s).toURI().toURL());
+ }
}
+
+ Class> clazz = loader.loadClass(versionInfo.mainClass);
+ Method method = clazz.getMethod("main", String[].class);
+ method.invoke(null, new Object[]{launchArgs});
+
+ // throw new RuntimeException("Game exited. Check latestlog.txt for more details.");
- }).start();
+ //}).start();
// JREUtils.launchJavaVM(javaArgList);
}
@@ -203,13 +196,13 @@ public final class Tools
}
}
minecraftArgs.add("--width");
- minecraftArgs.add(Integer.toString(GLFW.mGLFWWindowWidth));
+ minecraftArgs.add(Integer.toString(mGLFWWindowWidth));
minecraftArgs.add("--height");
- minecraftArgs.add(Integer.toString(GLFW.mGLFWWindowHeight));
+ minecraftArgs.add(Integer.toString(mGLFWWindowHeight));
minecraftArgs.add("--fullscreenWidth");
- minecraftArgs.add(Integer.toString(GLFW.mGLFWWindowWidth));
+ minecraftArgs.add(Integer.toString(mGLFWWindowWidth));
minecraftArgs.add("--fullscreenHeight");
- minecraftArgs.add(Integer.toString(GLFW.mGLFWWindowHeight));
+ minecraftArgs.add(Integer.toString(mGLFWWindowHeight));
String[] argsFromJson = JSONUtils.insertJSONValueList(
splitAndFilterEmpty(
versionInfo.minecraftArguments == null ?
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 0f9c3e14..98c72eab 100644
--- a/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java
+++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java
@@ -29,9 +29,7 @@ public class UIKit {
System.setProperty("os.name", osName);
}
- public static void callback_JavaGUIViewController_launchJarFile(final String filepath, int width, int height) {
- System.setProperty("cacio.managed.screensize", width + "x" + height);
-
+ public static void callback_JavaGUIViewController_launchJarFile(final String filepath) throws Throwable {
// Thread for refreshing the AWT buffer
new Thread(() -> {
try {
@@ -58,49 +56,27 @@ public class UIKit {
}
}, "AWTFBRefreshThread").start();
- // Thread for launching the JAR file
- new Thread(() -> {
- String mainClassName = null;
- try {
- JarFile jarfile = new JarFile(filepath);
- String mainClass = jarfile.getManifest().getMainAttributes().getValue("Main-Class");
- jarfile.close();
- if (mainClass == null) {
- throw new IllegalArgumentException("no main manifest attribute, in \"" + filepath + "\"");
- }
+ // Launch the JAR file
+ String mainClassName = null;
- PojavClassLoader loader = (PojavClassLoader) ClassLoader.getSystemClassLoader();
- loader.addURL(new File(filepath).toURI().toURL());
+ JarFile jarfile = new JarFile(filepath);
+ String mainClass = jarfile.getManifest().getMainAttributes().getValue("Main-Class");
+ jarfile.close();
+ if (mainClass == null) {
+ throw new IllegalArgumentException("no main manifest attribute, in \"" + filepath + "\"");
+ }
- // LabyMod Installer uses FlatLAF which has some macOS-specific codes, so we make it thinks it's running on Linux.
- patch_FlatLAF_setLinux();
+ PojavClassLoader loader = (PojavClassLoader) ClassLoader.getSystemClassLoader();
+ loader.addURL(new File(filepath).toURI().toURL());
- Class> clazz = loader.loadClass(mainClass);
- Method method = clazz.getMethod("main", String[].class);
- method.invoke(null, new Object[]{new String[]{}});
+ // LabyMod Installer uses FlatLAF which has some macOS-specific codes, so we make it thinks it's running on Linux.
+ patch_FlatLAF_setLinux();
- // throw new RuntimeException("Application exited");
- } catch (Throwable th) {
- Tools.showError(th, true);
- }
- }, "ModInstallerThread").start();
+ Class> clazz = loader.loadClass(mainClass);
+ Method method = clazz.getMethod("main", String[].class);
+ method.invoke(null, new Object[]{new String[]{}});
}
- public static void callback_SurfaceViewController_launchMinecraft(int width, int height, String rendererLibName) {
- MCOptionUtils.load();
- MCOptionUtils.set("overrideWidth", Integer.toString(width));
- MCOptionUtils.set("overrideHeight", Integer.toString(height));
- MCOptionUtils.save();
-
- System.setProperty("cacio.managed.screensize", width + "x" + height);
- System.setProperty("org.lwjgl.opengl.libname", rendererLibName);
-
- GLFW.internalChangeMonitorSize(width, height);
- CallbackBridge.mouseX = width / 2;
- CallbackBridge.mouseY = height / 2;
- PLaunchApp.launchMinecraft();
- }
-
public static void callback_SurfaceViewController_onTouch(int event, float x, float y) {
switch (event) {
case ACTION_DOWN:
@@ -110,7 +86,7 @@ public class UIKit {
CallbackBridge.mouseY = y;
}
break;
-
+
case ACTION_MOVE:
if (GLFW.mGLFWIsGrabbing) {
CallbackBridge.mouseX += x - CallbackBridge.mouseLastX;
@@ -136,7 +112,7 @@ public class UIKit {
String str = MCOptionUtils.get("guiScale");
guiScale = (str == null ? 0 :Integer.parseInt(str));
- int scale = Math.max(Math.min(GLFW.mGLFWWindowWidth / 320, GLFW.mGLFWWindowHeight / 240), 1);
+ int scale = Math.max(Math.min(Tools.mGLFWWindowWidth / 320, Tools.mGLFWWindowHeight / 240), 1);
if(scale < guiScale || guiScale == 0){
guiScale = scale;
}
diff --git a/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java b/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java
index 01191915..28f99718 100644
--- a/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java
+++ b/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java
@@ -11,6 +11,8 @@ import java.nio.*;
import javax.annotation.*;
+import net.kdt.pojavlaunch.Tools;
+
import org.lwjgl.*;
import org.lwjgl.opengl.GL;
import org.lwjgl.system.*;
@@ -484,7 +486,6 @@ public class GLFW
/* volatile */ public static GLFWWindowRefreshCallback mGLFWWindowRefreshCallback;
/* volatile */ public static GLFWWindowSizeCallback mGLFWWindowSizeCallback;
- volatile public static int mGLFWWindowWidth, mGLFWWindowHeight;
volatile public static double mGLFWCursorX, mGLFWCursorY, mGLFWCursorLastX, mGLFWCursorLastY;
private static GLFWGammaRamp mGLFWGammaRamp;
@@ -499,23 +500,26 @@ public class GLFW
public static boolean mGLFWIsGrabbing, mGLFWIsInputReady, mGLFWIsUseStackQueue = false;
public static final byte[] keyDownBuffer = new byte[317];
public static long mainContext = 0;
- static {
- try {
+ static {
+ try {
System.load(System.getenv("BUNDLE_PATH") + "/PojavLauncher");
} catch (UnsatisfiedLinkError e) {
e.printStackTrace();
}
-
- // Minecraft triggers a glfwPollEvents() on splash screen, so update window size there.
- CallbackBridge.receiveCallback(CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE, mGLFWWindowWidth, mGLFWWindowHeight, 0, 0);
- CallbackBridge.receiveCallback(CallbackBridge.EVENT_TYPE_WINDOW_SIZE, mGLFWWindowWidth, mGLFWWindowHeight, 0, 0);
- mGLFWErrorCallback = GLFWErrorCallback.createPrint();
- mGLFWKeyCodes = new ArrayMap<>();
+ // Minecraft triggers a glfwPollEvents() on splash screen, so update window size there.
+ // TODO objc-rewrite: commented out for testing only
+ //CallbackBridge.receiveCallback(CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE, Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight, 0, 0);
+ //CallbackBridge.receiveCallback(CallbackBridge.EVENT_TYPE_WINDOW_SIZE, Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight, 0, 0);
+
+ mGLFWErrorCallback = GLFWErrorCallback.createPrint();
+ mGLFWKeyCodes = new ArrayMap<>();
mGLFWWindowMap = new ArrayMap<>();
mGLFWVideoMode = new GLFWVidMode(ByteBuffer.allocateDirect(GLFWVidMode.SIZEOF));
+ internalChangeMonitorSize(Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight);
+
/*
memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.REDBITS, 8);
memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.GREENBITS, 8);
@@ -593,10 +597,10 @@ public class GLFW
}
public static void internalChangeMonitorSize(int width, int height) {
- mGLFWWindowWidth = width;
- mGLFWWindowHeight = height;
- memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.WIDTH, mGLFWWindowWidth);
- memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.HEIGHT, mGLFWWindowHeight);
+ Tools.mGLFWWindowWidth = width;
+ Tools.mGLFWWindowHeight = height;
+ memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.WIDTH, Tools.mGLFWWindowWidth);
+ memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.HEIGHT, Tools.mGLFWWindowHeight);
}
public static GLFWWindowProperties internalGetWindow(long window) {
@@ -671,7 +675,7 @@ public class GLFW
/*
try {
- mGLFWFramebufferSizeCallback.invoke(window, mGLFWWindowWidth, mGLFWWindowHeight);
+ mGLFWFramebufferSizeCallback.invoke(window, Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight);
} catch (Throwable th) {}
*/
@@ -781,7 +785,7 @@ public class GLFW
mGLFWWindowSizeCallback = GLFWWindowSizeCallback.createSafe(nglfwSetWindowSizeCallback(window, memAddressSafe(cbfun)));
try {
- mGLFWWindowSizeCallback.invoke(window, mGLFWWindowWidth, mGLFWWindowHeight);
+ mGLFWWindowSizeCallback.invoke(window, Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight);
} catch (Throwable th) {}
return lastCallback;
@@ -855,8 +859,8 @@ public class GLFW
xpos.put(0);
ypos.put(0);
- width.put(mGLFWWindowWidth);
- height.put(mGLFWWindowHeight);
+ width.put(Tools.mGLFWWindowWidth);
+ height.put(Tools.mGLFWWindowHeight);
}
@NativeType("GLFWmonitor *")
@@ -1101,11 +1105,11 @@ public class GLFW
case CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE:
case CallbackBridge.EVENT_TYPE_WINDOW_SIZE:
internalChangeMonitorSize((int)dataArr[1], (int)dataArr[2]);
- glfwSetWindowSize(ptr, mGLFWWindowWidth, mGLFWWindowHeight);
+ glfwSetWindowSize(ptr, Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight);
if ((int)dataArr[0] == CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE && mGLFWFramebufferSizeCallback != null) {
- mGLFWFramebufferSizeCallback.invoke(ptr, mGLFWWindowWidth, mGLFWWindowHeight);
+ mGLFWFramebufferSizeCallback.invoke(ptr, Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight);
} else if ((int)dataArr[0] == CallbackBridge.EVENT_TYPE_WINDOW_SIZE && mGLFWWindowSizeCallback != null) {
- mGLFWWindowSizeCallback.invoke(ptr, mGLFWWindowWidth, mGLFWWindowHeight);
+ mGLFWWindowSizeCallback.invoke(ptr, Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight);
}
break;
default:
@@ -1303,8 +1307,8 @@ return false;
xpos[0] = 0;
ypos[0] = 0;
- width[0] = mGLFWWindowWidth;
- height[0] = mGLFWWindowHeight;
+ width[0] = Tools.mGLFWWindowWidth;
+ height[0] = Tools.mGLFWWindowHeight;
}
/** Array version of: {@link #glfwGetMonitorPhysicalSize GetMonitorPhysicalSize} */
diff --git a/JavaApp/src/main/java/org/lwjgl/glfw/GLFWWindowProperties.java b/JavaApp/src/main/java/org/lwjgl/glfw/GLFWWindowProperties.java
index b7f42df8..15a6c668 100644
--- a/JavaApp/src/main/java/org/lwjgl/glfw/GLFWWindowProperties.java
+++ b/JavaApp/src/main/java/org/lwjgl/glfw/GLFWWindowProperties.java
@@ -1,10 +1,11 @@
package org.lwjgl.glfw;
import java.util.*;
+import net.kdt.pojavlaunch.Tools;
public class GLFWWindowProperties {
- public int width = GLFW.mGLFWWindowWidth;
- public int height = GLFW.mGLFWWindowHeight;
+ public int width = Tools.mGLFWWindowWidth;
+ public int height = Tools.mGLFWWindowHeight;
public float x, y;
public CharSequence title;
public boolean shouldClose, isInitialSizeCalled, isCursorEntered;
diff --git a/Natives/CMakeLists.txt b/Natives/CMakeLists.txt
index be708ccd..52b30b38 100644
--- a/Natives/CMakeLists.txt
+++ b/Natives/CMakeLists.txt
@@ -50,6 +50,7 @@ target_link_libraries(libOSMesaOverride.dylib ${OSMESA_LIB})
add_executable(PojavLauncher
main.m
+ main_hook.m
log.m
JavaLauncher.m
external/fishhook/fishhook.c
diff --git a/Natives/CustomControlsViewController.m b/Natives/CustomControlsViewController.m
index b97bb3b4..a475d517 100644
--- a/Natives/CustomControlsViewController.m
+++ b/Natives/CustomControlsViewController.m
@@ -129,7 +129,7 @@ NSMutableArray *keyCodeMap, *keyValueMap;
[self.offsetView addGestureRecognizer:longpressGesture];
self.currentFileName = [getPreference(@"default_ctrl") stringByDeletingPathExtension];
[self initKeyCodeMap];
- [self loadControlFile:[NSString stringWithFormat:@"%s/%@", getenv("POJAV_PATH_CONTROL"), getPreference(@"default_ctrl")]];
+ [self loadControlFile:[NSString stringWithFormat:@"%s/controlmap/%@", getenv("POJAV_HOME"), getPreference(@"default_ctrl")]];
}
- (void)loadControlFile:(NSString *)controlFilePath {
@@ -210,7 +210,7 @@ NSMutableArray *keyCodeMap, *keyValueMap;
- (void)actionMenuSave {
UIAlertController *controller = [UIAlertController alertControllerWithTitle: @"Save"
- message:[NSString stringWithFormat:@"File will be saved to %s directory.", getenv("POJAV_PATH_CONTROL")]
+ message:[NSString stringWithFormat:@"File will be saved to %s/controlmap directory.", getenv("POJAV_HOME")]
preferredStyle:UIAlertControllerStyleAlert];
[controller addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = @"Name";
@@ -232,7 +232,7 @@ NSMutableArray *keyCodeMap, *keyValueMap;
return;
}
NSString *jsonStr = [NSString stringWithUTF8String:jsonData.bytes];
- BOOL success = [jsonStr writeToFile:[NSString stringWithFormat:@"%s/%@.json", getenv("POJAV_PATH_CONTROL"), field.text] atomically:YES encoding:NSUTF8StringEncoding error:&error];
+ BOOL success = [jsonStr writeToFile:[NSString stringWithFormat:@"%s/controlmap/%@.json", getenv("POJAV_HOME"), field.text] atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (!success) {
showDialog(self, @"Error while saving file", error.localizedDescription);
return;
@@ -263,14 +263,14 @@ NSMutableArray *keyCodeMap, *keyValueMap;
- (void)actionMenuLoad {
[self actionOpenFilePicker:^void(NSString* name) {
self.currentFileName = name;
- [self loadControlFile:[NSString stringWithFormat:@"%s/%@.json", getenv("POJAV_PATH_CONTROL"), name]];
+ [self loadControlFile:[NSString stringWithFormat:@"%s/controlmap/%@.json", getenv("POJAV_HOME"), name]];
}];
}
- (void)actionMenuSetDef {
[self actionOpenFilePicker:^void(NSString* name) {
self.currentFileName = name;
- [self loadControlFile:[NSString stringWithFormat:@"%s/%@.json", getenv("POJAV_PATH_CONTROL"), name]];
+ [self loadControlFile:[NSString stringWithFormat:@"%s/controlmap/%@.json", getenv("POJAV_HOME"), name]];
setPreference(@"default_ctrl", [NSString stringWithFormat:@"%@.json", name]);
}];
}
diff --git a/Natives/JavaGUIViewController.m b/Natives/JavaGUIViewController.m
index 194d1c56..e94748e0 100644
--- a/Natives/JavaGUIViewController.m
+++ b/Natives/JavaGUIViewController.m
@@ -1,4 +1,5 @@
#import "JavaGUIViewController.h"
+#import "JavaLauncher.h"
#import "LauncherPreferences.h"
#import "ios_uikit_bridge.h"
#include "utils.h"
@@ -10,6 +11,12 @@ jclass class_CTCAndroidInput;
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);
+ });
+ }
+
int *tmpArray = (*env)->GetIntArrayElements(env, jreRgbArray, 0);
memcpy(rgbArray, tmpArray, savedWidth * savedHeight * 4);
(*env)->ReleaseIntArrayElements(env, jreRgbArray, tmpArray, JNI_ABORT);
@@ -106,14 +113,16 @@ const void * _CGDataProviderGetBytePointerCallbackAWT(void *info) {
rgbArray = calloc(4, (size_t) (savedWidth * savedHeight));
- UIKit_launchJarFile(self.filepath.UTF8String);
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ launchJVM(@".LaunchJAR", self.filepath, savedWidth * resolutionScale, savedHeight * resolutionScale);
+ });
}
- (void)surfaceOnClick:(UITapGestureRecognizer *)sender {
if (method_ReceiveInput == NULL) {
- class_CTCAndroidInput = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "net/java/openjdk/cacio/ctc/CTCAndroidInput");
+ class_CTCAndroidInput = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "net/java/openjdk/cacio/ctc/CTCAndroidInput");
assert(class_CTCAndroidInput != NULL);
- method_ReceiveInput = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, class_CTCAndroidInput, "receiveData", "(IIIII)V");
+ method_ReceiveInput = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, class_CTCAndroidInput, "receiveData", "(IIIII)V");
assert(method_ReceiveInput != NULL);
}
@@ -123,20 +132,20 @@ const void * _CGDataProviderGetBytePointerCallbackAWT(void *info) {
CGPoint location = [sender locationInView:sender.view];
CGFloat x = location.x * screenScale * resolution;
CGFloat y = location.y * screenScale * resolution;
- (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
- runtimeJNIEnvPtr_JRE,
+ (*runtimeJNIEnvPtr)->CallStaticVoidMethod(
+ runtimeJNIEnvPtr,
class_CTCAndroidInput,
method_ReceiveInput,
EVENT_TYPE_CURSOR_POS, (int)x, (int)y, 0, 0
);
- (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
- runtimeJNIEnvPtr_JRE,
+ (*runtimeJNIEnvPtr)->CallStaticVoidMethod(
+ runtimeJNIEnvPtr,
class_CTCAndroidInput,
method_ReceiveInput,
EVENT_TYPE_MOUSE_BUTTON, BUTTON1_DOWN_MASK, 1, 0, 0
);
- (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
- runtimeJNIEnvPtr_JRE,
+ (*runtimeJNIEnvPtr)->CallStaticVoidMethod(
+ runtimeJNIEnvPtr,
class_CTCAndroidInput,
method_ReceiveInput,
EVENT_TYPE_MOUSE_BUTTON, BUTTON1_DOWN_MASK, 0, 0, 0
diff --git a/Natives/JavaLauncher.h b/Natives/JavaLauncher.h
index ce0e43b1..5482b689 100644
--- a/Natives/JavaLauncher.h
+++ b/Natives/JavaLauncher.h
@@ -1,7 +1,20 @@
#pragma once
#include
+#include "jni.h"
-static BOOL started = NO;
+typedef jint JLI_Launch_func(int argc, char ** argv, /* main argc, argc */
+ int jargc, const char** jargv, /* java args */
+ int appclassc, const char** appclassv, /* app classpath */
+ const char* fullversion, /* full version defined */
+ const char* dotversion, /* dot version defined */
+ const char* pname, /* program name */
+ const char* lname, /* launcher name */
+ jboolean javaargs, /* JAVA_ARGS */
+ jboolean cpwildcard, /* classpath wildcard*/
+ jboolean javaw, /* windows-only javaw */
+ jint ergo /* ergonomics class policy */
+);
+JLI_Launch_func *pJLI_Launch;
-int launchJVM(int argc, char *argv[]);
+int launchJVM(NSString *username, NSString *selectedVersion, int width, int height);
diff --git a/Natives/JavaLauncher.m b/Natives/JavaLauncher.m
index 89c70722..54cad6df 100644
--- a/Natives/JavaLauncher.m
+++ b/Natives/JavaLauncher.m
@@ -3,45 +3,23 @@
#include
#include
#include
-#include
#include
#include
#include
#include
+#include
#include
-#include
-#include
-#include
-#include
-
-#include "jni.h"
#include "log.h"
#include "utils.h"
#include "JavaLauncher.h"
-#include "external/fishhook/fishhook.h"
-#import "customcontrols/CustomControlsUtils.h"
#import "LauncherPreferences.h"
-// PojavLancher: fixme: are these wrong?
-#define FULL_VERSION "1.8.0-internal"
-#define DOT_VERSION "1.8"
-
-#if CONFIG_RELEASE == 1
-# define CONFIG_TYPE "release"
-#else
-# define CONFIG_TYPE "debug"
-#endif
-
-#ifndef CONFIG_COMMIT
-# define CONFIG_COMMIT unspecified
-#endif
+#define fm NSFileManager.defaultManager
static char java_libs_path[2048];
static char args_path[2048];
-static char env_path[2048];
-static char log_path[2048];
extern char **environ;
@@ -53,33 +31,8 @@ static const jboolean const_javaw = JNI_FALSE;
static const jboolean const_cpwildcard = JNI_TRUE;
static const jint const_ergo_class = 0; // DEFAULT_POLICY
-typedef jint JLI_Launch_func(int argc, char ** argv, /* main argc, argc */
- int jargc, const char** jargv, /* java args */
- int appclassc, const char** appclassv, /* app classpath */
- const char* fullversion, /* full version defined */
- const char* dotversion, /* dot version defined */
- const char* pname, /* program name */
- const char* lname, /* launcher name */
- jboolean javaargs, /* JAVA_ARGS */
- jboolean cpwildcard, /* classpath wildcard*/
- jboolean javaw, /* windows-only javaw */
- jint ergo /* ergonomics class policy */
-);
-
-int main(int argc, char * argv[]);
-
-static int (*orig_dladdr)(const void* addr, Dl_info* info);
-static void* (*orig_dlopen)(const char* path, int mode);
-//static void* (*orig_mmap)(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
-static char* (*orig_realpath)(const char *restrict path, char *restrict resolved_path);
-//static void (*orig_sys_icache_invalidate)(void *start, size_t len);
-
static int margc = 0;
static char* margv[1000];
-static int pfd[2];
-static int log_fd;
-static pthread_t logger;
-static BOOL filteredSessionID;
const char *javaHome;
const char *renderer;
@@ -88,149 +41,10 @@ const char *multidir;
char *homeDir;
-NSString *javaHome_pre;
NSString *renderer_pre;
NSString *allocmem_pre;
NSString *multidir_pre;
-int hooked_dladdr(const void* addr, Dl_info* info) {
- //NSLog(@"hook dladdr(%p, %p)", addr, info);
- int retVal = orig_dladdr(addr, info);
- if (addr == main) {
- //NSLog(@"hooked dladdr");
- info->dli_fname = getenv("JAVA_EXT_EXECNAME");
- } else if (retVal != 0) {
- //NSLog(@"hooked dladdr");
- char *libname = basename((char *)info->dli_fname);
- char src[2048], dst[2048];
- sprintf((char *)src, "%s/Frameworks", getenv("BUNDLE_PATH"));
- if (0 == strncmp(info->dli_fname, src, strlen(src))) {
- if (0 == strncmp(libname, "libjli.dylib", 12)) {
- info->dli_fname = getenv("INTERNAL_JLI_PATH");
- } else if (0 == strncmp(libname, "libjvm.dylib", 12)) {
- sprintf((char *)dst, "%s/lib/server/libjvm.dylib", getenv("JAVA_HOME"));
- info->dli_fname = (char *)dst;
- }
- }
- }
- //if (retVal) NSLog(@"dli_fname=%s", info->dli_fname);
- return retVal;
-}
-
-void* hooked_dlopen(const char* path, int mode) {
- void *handle = orig_dlopen(path, mode);
- if (handle) {
- return handle;
- }
-
- char src[2048], dst[2048];
- sprintf((char *)src, "%s/Frameworks", getenv("BUNDLE_PATH"));
- //NSLog(@"path=%s, src=%s, length=%lu, compare=%d", path, src, strlen(src), strncmp(path, src, strlen(src)));
- if (!strncmp(path, src, strlen(src))) {
- //NSLog(@"hooked dlopen %s", path);
- char *libname = basename((char *)path);
- sprintf((char *)dst, "%s/%s.framework/%s", src, libname, libname);
- handle = orig_dlopen(dst, mode);
- if (handle) {
- dlerror(); // clear error
- }
- }
-
- return handle;
-}
-
-/*
-void *hooked_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) {
- NSLog(@"mmap(%p, %ld, %d, %d, %d, %lld)", addr, len, prot, flags, fd, offset);
-
- if (flags & MAP_JIT) {
- NSLog(@"'-> Found JIT mmap");
- //flags &= ~MAP_JIT;
- }
-
- // raise(SIGINT);
- return orig_mmap(addr, len, prot, flags, fd, offset);
-}
-*/
-
-char *hooked_realpath(const char *restrict path, char *restrict resolved_path) {
- //NSLog(@"hook realpath %s", path);
- if (0 == strncmp(path, javaHome, strlen(javaHome))) {
- strcpy(resolved_path, path);
- return resolved_path;
- } else {
- return orig_realpath(path, resolved_path);
- }
-}
-
-/*
-void hooked_sys_icache_invalidate(void *start, size_t len) {
- // mprotect(start, 16384, PROT_EXEC | PROT_READ);
- // NSLog(@"mprotect errno %d", errno);
- orig_sys_icache_invalidate(start, len);
-}
-*/
-
-static void *logger_thread() {
- ssize_t rsize;
- char buf[2048];
- while((rsize = read(pfd[0], buf, sizeof(buf)-1)) > 0) {
- // Filter out Session ID here
- int index;
- if (!filteredSessionID) {
- char *sessionStr = strstr(buf, "(Session ID is ");
- if (sessionStr) {
- char *censorStr = "(Session ID is )\n\0";
- strcpy(sessionStr, censorStr);
- rsize = strlen(buf);
- filteredSessionID = true;
- }
- }
- write(log_fd, buf, rsize);
- }
- close(log_fd);
- return NULL;
-}
-
-void init_hookFunctions() {
- // if (!started && strncmp(argv[0], "/Applications", 13))
- // Jailed only: hook some functions for symlinked JRE home dir
- int retval = rebind_symbols((struct rebinding[3]){
- {"dladdr", hooked_dladdr, (void *)&orig_dladdr},
- {"dlopen", hooked_dlopen, (void *)&orig_dlopen},
- //{"realpath", hooked_realpath, (void *)&orig_realpath},
- {"realpath$DARWIN_EXTSN", hooked_realpath, (void *)&orig_realpath}
- //{"mmap", hooked_mmap, (void *)&orig_mmap},
- //{"sys_icache_invalidate", hooked_sys_icache_invalidate, (void *)&orig_sys_icache_invalidate}
- }, 3);
- NSLog(@"hook retval = %d", retval);
-}
-
-void init_loadCustomEnv() {
- FILE *envFile = fopen(env_path, "r");
-
- regLog("[Pre-init] Reading custom environment variables (custom_env.txt), opened=%d\n", envFile != NULL);
-
- if (envFile) {
- char *line = NULL;
- size_t len = 0;
- ssize_t read;
- while ((read = getline(&line, &len, envFile)) != -1) {
- if (line[0] == '#' || line[0] == '\n') continue;
- if (line[read-1] == '\n') {
- line[read-1] = '\0';
- }
- if (strchr(line, '=') != NULL) {
- regLog("[Pre-init] Added custom env: %s", line);
- setenv(strtok(line, "="), strtok(NULL, "="), 1);
- } else {
- regLog("[Pre-init] Warning: skipped empty value custom env: %s", line);
- }
- }
- fclose(envFile);
- }
-}
-
void init_loadCustomJvmFlags() {
NSString *jvmargs = getPreference(@"java_args");
BOOL isFirstArg = YES;
@@ -250,193 +64,51 @@ void init_loadCustomJvmFlags() {
}
}
-void init_migrateToPlist(char* prefKey, char* filename) {
- // NSString *readmeStr = @"#README - this file has been merged into launcher_preferences.plist";
- NSError *error;
- NSString *str, *path_str;
-
- // overrideargs.txt
- path_str = [NSString stringWithFormat:@"%s/%s", getenv("POJAV_HOME"), filename];
- str = [NSString stringWithContentsOfFile:path_str encoding:NSUTF8StringEncoding error:&error];
- if (error == nil && ![str hasPrefix:@"#README"]) {
- setPreference(@(prefKey), str);
- [@"#README - this file has been merged into launcher_preferences.plist" writeToFile:path_str atomically:YES encoding:NSUTF8StringEncoding error:nil];
- }
-}
-
-void init_logDeviceAndVer (char *argument) {
- struct utsname systemInfo;
- uname(&systemInfo);
- // Hardware + software
- const char *deviceHardware = systemInfo.machine;
- const char *deviceSoftware = [[[UIDevice currentDevice] systemVersion] cStringUsingEncoding:NSUTF8StringEncoding];
-
- // Jailbreak
- const char *jbStrap;
- if (strncmp(argument, "/Applications", 13) == 0) {
- if ([[NSFileManager defaultManager] fileExistsAtPath:@"/.procursus_strapped"]) {
- jbStrap = "Procursus";
- } else {
- jbStrap = "Other";
- }
- regLog("[Pre-Init] %s with iOS %s (%s)", deviceHardware, deviceSoftware, jbStrap);
- } else {
- regLog("[Pre-Init] %s with iOS %s", deviceHardware, deviceSoftware);
- }
-
- // PojavLauncher version
- regLog("[Pre-Init] PojavLauncher version: %s - %s", CONFIG_TYPE, CONFIG_COMMIT);
-
- setenv("POJAV_DETECTEDHW", deviceHardware, 1);
- setenv("POJAV_DETECTEDSW", deviceSoftware, 1);
- if (strncmp(argument, "/Applications", 13) == 0) {
- setenv("POJAV_DETECTEDJB", jbStrap, 1);
- }
-}
-
-void init_redirectStdio(char* homeDir) {
- regLog("[Pre-init] Staring logging STDIO as jrelog:V\n");
- // Redirect stdio to latestlog.txt
- char newname[2048];
- sprintf(newname, "%s/latestlog.old.txt", homeDir);
- rename(log_path, newname);
- FILE* logFile = fopen(log_path, "w");
- if (!logFile) {
- regLog("[Pre-init] Error: failed to open %s: %s", log_path, strerror(errno));
- assert(0 && "Failed to open latestlog.txt. Check oslog for more details.");
- }
- log_fd = fileno(logFile);
- setvbuf(stdout, 0, _IOLBF, 0); // make stdout line-buffered
- setvbuf(stderr, 0, _IONBF, 0); // make stderr unbuffered
-
- /* create the pipe and redirect stdout and stderr */
- pipe(pfd);
- dup2(pfd[1], 1);
- dup2(pfd[1], 2);
-
- /* spawn the logging thread */
- if(pthread_create(&logger, 0, logger_thread, 0) == -1) {
- char *fail_str = "Failed to start logging!";
- write(log_fd, fail_str, strlen(fail_str));
- close(log_fd);
- }
- pthread_detach(logger);
-}
-
-void environmentFailsafes(char *argv[]) {
- if (strncmp(argv[0], "/Applications", 13) == 0) {
- if (0 == access("/usr/lib/jvm/java-8-openjdk/", F_OK)) {
- javaHome_pre = @"/usr/lib/jvm/java-8-openjdk";
- } else if (0 == access("/usr/lib/jvm/java-16-openjdk/", F_OK)) {
+NSString* environmentFailsafes() {
+ NSString *javaHome_pre;
+ if (strncmp(getenv("BUNDLE_PATH"), "/Applications", 13) == 0) {
+ if ([fm fileExistsAtPath:JRE8_HOME_JB]) {
+ javaHome_pre = JRE8_HOME_JB;
+ } else if ([fm fileExistsAtPath:JRE16_HOME_JB]) {
regLog("[Pre-init] Java 8 wasn't found on your device. Install Java 8 for more compatibility and the mod installer.");
- javaHome_pre = @"/usr/lib/jvm/java-16-openjdk";
- } else if (0 == access("/usr/lib/jvm/java-17-openjdk/", F_OK)) {
+ javaHome_pre = JRE16_HOME_JB;
+ } else if ([fm fileExistsAtPath:JRE17_HOME_JB]) {
regLog("[Pre-init] Java 8 wasn't found on your device. Install Java 8 for more compatibility and the mod installer.");
- javaHome_pre = @"/usr/lib/jvm/java-17-openjdk";
+ javaHome_pre = JRE17_HOME_JB;
} else {
regLog("[Pre-init] FATAL ERROR: Java wasn't found on your device, PojavLauncher cannot continue, aborting.");
abort();
}
- javaHome = [javaHome_pre cStringUsingEncoding:NSUTF8StringEncoding];
- setPreference(@"java_home", javaHome_pre);
} else {
- asprintf((char **)&javaHome, "%s/jre", homeDir);
+ javaHome_pre = [NSString stringWithFormat:@"%s/jre", getenv("POJAV_HOME")];
}
+
+ javaHome = javaHome_pre.UTF8String;
+ setPreference(@"java_home", javaHome_pre);
+ return javaHome_pre;
}
-int launchJVM(int argc, char *argv[]) {
- if (0 != [[NSFileManager defaultManager] fileExistsAtPath:@"/var/mobile/Documents/.pojavlauncher"] && 0 == [[NSFileManager defaultManager] fileExistsAtPath:@"/var/mobile/Documents/.pojavlauncher/migration_complete"]) {
- NSString *newDir = @"/usr/share/pojavlauncher";
- if([[[UIDevice currentDevice] systemVersion] containsString:@"15."]) {
- newDir = @"/private/preboot/procursus/usr/share/pojavlauncher";
- }
- NSString *oldDir = @"/var/mobile/Documents/.pojavlauncher";
- NSFileManager *fm = [NSFileManager defaultManager];
- NSArray *files = [fm contentsOfDirectoryAtPath:oldDir error:nil];
- for (NSString *file in files) {
- [fm moveItemAtPath:[oldDir stringByAppendingPathComponent:file] toPath:[newDir stringByAppendingPathComponent:file] error:nil];
- }
- [fm removeItemAtPath:oldDir error:nil];
- symlink([newDir cStringUsingEncoding:NSUTF8StringEncoding], [oldDir cStringUsingEncoding:NSUTF8StringEncoding]);
- FILE* file_ptr = fopen("/var/mobile/Documents/.pojavlauncher/migration_complete", "w");
- fprintf(file_ptr, "#README - The PojavLauncher data directory is now %s. All of your existing data has been moved to the new location.", [newDir cStringUsingEncoding:NSUTF8StringEncoding]);
- fclose(file_ptr);
- }
-
- if (!started) {
- setenv("EXEC_PATH", argv[0], 1);
- setenv("BUNDLE_PATH", dirname(argv[0]), 1);
-
- // Are we running on a jailbroken environment?
- if (strncmp(argv[0], "/Applications", 13) == 0) {
- setenv("HOME", "/usr/share", 1);
- setenv("OLD_POJAV_HOME", "/var/mobile/Documents/.pojavlauncher", 1);
- homeDir = "/usr/share/pojavlauncher";
- } else {
- char pojavHome[2048];
- sprintf(pojavHome, "%s/Documents", getenv("HOME"));
- homeDir = (char *) pojavHome;
-
- init_hookFunctions();
- }
- setenv("POJAV_HOME", homeDir, 1);
- } else {
- homeDir = getenv("POJAV_HOME");
- }
-
- init_loadCustomEnv();
-
- loadPreferences();
-
- init_migrateToPlist("selected_version", "config_ver.txt");
- init_migrateToPlist("java_args", "overrideargs.txt");
-
- sprintf((char*) env_path, "%s/custom_env.txt", homeDir);
- sprintf((char*) log_path, "%s/latestlog.txt", homeDir);
+int launchJVM(NSString *username, NSString *selectedVersion, int width, int height) {
sprintf((char*) java_libs_path, "%s/libs", getenv("BUNDLE_PATH"));
-
- mkdir(dirname(log_path), 755);
- if (!started) {
- init_redirectStdio(homeDir);
- }
-
- init_logDeviceAndVer(argv[0]);
regLog("[Pre-init] Beginning JVM launch\n");
-
- char javaAwtPath[4096];
- // I accidentally patched a bit wrong, the value should be a path containing libawt_xawt.dylib, but here is libawt.dylib path (no need to exist)
- sprintf(javaAwtPath, "%s/Frameworks/libawt.dylib", getenv("BUNDLE_PATH"));
- setenv("JAVA_AWT_PATH", javaAwtPath, 1);
- // setenv("LIBGL_FB", "2", 1);
- setenv("LIBGL_MIPMAP", "3", 1);
-
- // Fix white color on banner and sheep, since GL4ES 1.1.5
- setenv("LIBGL_NORMALIZE", "1", 1);
-
- // Disable overloaded functions hack for Minecraft 1.17+
- setenv("LIBGL_NOINTOVLHACK", "1", 1);
-
- // Override OpenGL version to 4.1 for Zink
- setenv("MESA_GL_VERSION_OVERRIDE", "4.1", 1);
-
- javaHome_pre = getPreference(@"java_home");
- javaHome = [javaHome_pre cStringUsingEncoding:NSUTF8StringEncoding];
- if ([javaHome_pre length] == 0) {
- environmentFailsafes(argv);
+ NSString *javaHome_pre = getPreference(@"java_home");
+ javaHome = javaHome_pre.UTF8String;
+ if (javaHome_pre.length == 0) {
+ environmentFailsafes();
regLog("[Pre-init] JAVA_HOME environment variable was not set. Defaulting to %s for future use.\n", javaHome);
} else {
- if (0 == [[NSFileManager defaultManager] fileExistsAtPath:javaHome_pre]) {
+ if (![NSFileManager.defaultManager fileExistsAtPath:javaHome_pre]) {
regLog("[Pre-Init] Failed to locate %s. Restoring default value for JAVA_HOME.", javaHome);
- environmentFailsafes(argv);
+ environmentFailsafes();
} else {
regLog("[Pre-Init] Restored preference: JAVA_HOME is set to %s\n", javaHome);
}
}
setenv("JAVA_HOME", javaHome, 1);
- if (!started && strncmp(argv[0], "/Applications", 13)) {
+ if (strncmp(getenv("BUNDLE_PATH"), "/Applications", 13)) {
char src[2048], dst[2048];
// Symlink frameworks -> dylibs on jailed environment
@@ -523,27 +195,20 @@ int launchJVM(int argc, char *argv[]) {
}
renderer_pre = getPreference(@"renderer");
- renderer = [renderer_pre cStringUsingEncoding:NSUTF8StringEncoding];
- if ([renderer_pre length] == 0) {
+ renderer = renderer_pre.UTF8String;
+ if (renderer_pre.length == 0) {
renderer_pre = @"libgl4es_114.dylib";
setPreference(@"renderer", renderer_pre);
renderer = [renderer_pre cStringUsingEncoding:NSUTF8StringEncoding];
- setenv("POJAV_RENDERER", renderer, 1);
regLog("[Pre-init] RENDERER environment variable was not set. Defaulting to %s for future use.\n", renderer);
} else {
regLog("[Pre-Init] Restored preference: RENDERER is set to %s\n", renderer);
}
+ setenv("POJAV_RENDERER", renderer, 1);
allocmem_pre = [getPreference(@"allocated_memory") stringValue];
allocmem = [allocmem_pre cStringUsingEncoding:NSUTF8StringEncoding];
- char *controlPath;
- asprintf(&controlPath, "%s/controlmap", homeDir);
- mkdir(controlPath, S_IRWXU | S_IRWXG | S_IRWXO);
- setenv("POJAV_PATH_CONTROL", controlPath, 1);
- free(controlPath);
- generateAndSaveDefaultControl();
-
char classpath[10000];
// "/Applications/PojavLauncher.app/libs/launcher.jar:/Applications/PojavLauncher.app/libs/ExagearApacheCommons.jar:/Applications/PojavLauncher.app/libs/gson-2.8.6.jar:/Applications/PojavLauncher.app/libs/jsr305.jar:/Applications/PojavLauncher.app/libs/lwjgl3-minecraft.jar";
@@ -566,73 +231,37 @@ int launchJVM(int argc, char *argv[]) {
closedir(d);
}
debugLog("[Pre-init] Classpath generated: %s", classpath);
-
- multidir_pre = getPreference(@"game_directory");
- multidir = [multidir_pre cStringUsingEncoding:NSUTF8StringEncoding];
- if ([multidir_pre length] == 0) {
- multidir_pre = @"default";
- multidir = [multidir_pre cStringUsingEncoding:NSUTF8StringEncoding];
- setPreference(@"game_directory", multidir_pre);
- regLog("[Pre-init] MULTI_DIR environment variable was not set. Defaulting to %s for future use.\n", multidir);
- } else {
- multidir = [multidir_pre cStringUsingEncoding:NSUTF8StringEncoding];
- regLog("[Pre-init] Restored preference: MULTI_DIR is set to %s\n", multidir);
- }
- char *multidir_char, *librarySym;
- asprintf(&multidir_char, "%s/instances/%s", getenv("POJAV_HOME"), multidir);
- asprintf(&librarySym, "%s/Library/Application Support/minecraft", getenv("POJAV_HOME"));
- remove(librarySym);
- if (0 != access(multidir_char, F_OK)) {
- mkdir(multidir_char, 755);
- }
- symlink(multidir_char, librarySym);
- setenv("POJAV_GAME_DIR", librarySym, 1);
-
- if (0 == access("/var/mobile/Documents/minecraft", F_OK)) {
- rename("/var/mobile/Documents/minecraft", multidir_char);
- regLog("[Pre-Init] Migrated old minecraft folder to new location.");
- }
-
- if (0 == access("/var/mobile/Documents/Library", F_OK)) {
- remove("/var/mobile/Documents/Library");
- }
+
// Check if JVM restarts
- if (!started) {
- char *frameworkPath, *javaPath, *jnaLibPath, *userDir, *userHome, *memMin, *memMax, *arcDNS;
- asprintf(&frameworkPath, "-Djava.library.path=%s/Frameworks:%s/Frameworks/libOSMesaOverride.dylib.framework", getenv("BUNDLE_PATH"), getenv("BUNDLE_PATH"));
- asprintf(&javaPath, "%s/bin/java", javaHome);
- asprintf(&jnaLibPath, "-Djna.boot.library.path=%s/Frameworks/libjnidispatch.dylib.framework", getenv("BUNDLE_PATH"));
- asprintf(&userDir, "-Duser.dir=%s", getenv("POJAV_GAME_DIR"));
- asprintf(&userHome, "-Duser.home=%s", getenv("POJAV_HOME"));
- asprintf(&memMin, "-Xms%sM", allocmem);
- asprintf(&memMax, "-Xmx%sM", allocmem);
- asprintf(&arcDNS, "-javaagent:%s/arc_dns_injector.jar=23.95.137.176", java_libs_path);
- NSLog(@"[Pre-init] Java executable path: %s", javaPath);
- setenv("JAVA_EXT_EXECNAME", javaPath, 1);
+ char *frameworkPath, *javaPath, *jnaLibPath, *userDir, *userHome, *memMin, *memMax, *arcDNS;
+ asprintf(&frameworkPath, "-Djava.library.path=%s/Frameworks:%s/Frameworks/libOSMesaOverride.dylib.framework", getenv("BUNDLE_PATH"), getenv("BUNDLE_PATH"));
+ asprintf(&javaPath, "%s/bin/java", javaHome);
+ asprintf(&jnaLibPath, "-Djna.boot.library.path=%s/Frameworks/libjnidispatch.dylib.framework", getenv("BUNDLE_PATH"));
+ asprintf(&userDir, "-Duser.dir=%s", getenv("POJAV_GAME_DIR"));
+ asprintf(&userHome, "-Duser.home=%s", getenv("POJAV_HOME"));
+ asprintf(&memMin, "-Xms%sM", allocmem);
+ asprintf(&memMax, "-Xmx%sM", allocmem);
+ asprintf(&arcDNS, "-javaagent:%s/arc_dns_injector.jar=23.95.137.176", java_libs_path);
+ NSLog(@"[Pre-init] Java executable path: %s", javaPath);
+ setenv("JAVA_EXT_EXECNAME", javaPath, 1);
- chdir(librarySym);
-
- margv[margc++] = javaPath;
- margv[margc++] = "-XstartOnFirstThread";
- margv[margc++] = "-Djava.system.class.loader=net.kdt.pojavlaunch.PojavClassLoader";
- margv[margc++] = memMin;
- margv[margc++] = memMax;
- margv[margc++] = frameworkPath;
- margv[margc++] = jnaLibPath;
- margv[margc++] = userDir;
- margv[margc++] = userHome;
- margv[margc++] = "-Dorg.lwjgl.system.allocator=system";
- margv[margc++] = "-Dlog4j2.formatMsgNoLookups=true";
- if([getPreference(@"arccapes_enable") boolValue]) {
- margv[margc++] = arcDNS;
- }
- NSString *selectedAccount = getPreference(@"internal_selected_account");
- if (selectedAccount != nil) {
- margv[margc++] = (char *) [NSString stringWithFormat:@"-Dpojav.selectedAccount=%@", selectedAccount].UTF8String;
- }
- } else {
- setenv("POJAV_RENDERER", renderer, 1);
- regLog("[Pre-init] RENDERER has been set to %s", getenv("POJAV_RENDERER"));
+ margv[margc++] = javaPath;
+ margv[margc++] = "-XstartOnFirstThread";
+ margv[margc++] = "-Djava.system.class.loader=net.kdt.pojavlaunch.PojavClassLoader";
+ margv[margc++] = memMin;
+ margv[margc++] = memMax;
+ margv[margc++] = frameworkPath;
+ margv[margc++] = jnaLibPath;
+ margv[margc++] = userDir;
+ margv[margc++] = userHome;
+ margv[margc++] = "-Dorg.lwjgl.system.allocator=system";
+ margv[margc++] = "-Dlog4j2.formatMsgNoLookups=true";
+ if([getPreference(@"arccapes_enable") boolValue]) {
+ margv[margc++] = arcDNS;
+ }
+ NSString *selectedAccount = getPreference(@"internal_selected_account");
+ if (selectedAccount != nil) {
+ margv[margc++] = (char *) [NSString stringWithFormat:@"-Dpojav.selectedAccount=%@", selectedAccount].UTF8String;
}
// Load java
@@ -651,86 +280,68 @@ int launchJVM(int argc, char *argv[]) {
return -1;
}
- if (!started) {
- // 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++] = "-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";
+ // 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++] = "-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";
- // Generate Caciocavallo bootclasspath
- char cacio_libs_path[2048];
- char cacio_classpath[8192];
- sprintf((char*) cacio_libs_path, "%s/libs_caciocavallo", getenv("BUNDLE_PATH"));
- cplen = sprintf(cacio_classpath, "-Xbootclasspath/p");
- d = opendir(cacio_libs_path);
- int skip = 2;
- if (d) {
- while ((dir = readdir(d)) != NULL) {
- if (skip > 0) {
- --skip;
- continue;
- }
- cplen += sprintf(cacio_classpath + cplen, ":%s/%s", cacio_libs_path, dir->d_name);
+ // Generate Caciocavallo bootclasspath
+ char cacio_libs_path[2048];
+ char cacio_classpath[8192];
+ sprintf((char*) cacio_libs_path, "%s/libs_caciocavallo", getenv("BUNDLE_PATH"));
+ cplen = sprintf(cacio_classpath, "-Xbootclasspath/p");
+ d = opendir(cacio_libs_path);
+ int skip = 2;
+ if (d) {
+ while ((dir = readdir(d)) != NULL) {
+ if (skip > 0) {
+ --skip;
+ continue;
}
- closedir(d);
+ cplen += sprintf(cacio_classpath + cplen, ":%s/%s", cacio_libs_path, dir->d_name);
}
- margv[margc++] = cacio_classpath;
+ closedir(d);
}
- } else if (!started) {
- // Opens to ARC DNS
- margv[margc++] = "--add-opens=java.base/java.net=ALL-UNNAMED";
+ margv[margc++] = cacio_classpath;
}
- if (!started) {
- init_loadCustomJvmFlags();
- }
+ init_loadCustomJvmFlags();
regLog("[Init] Found JLI lib");
- if (!started) {
- margv[margc++] = "-cp";
- margv[margc++] = classpath;
- margv[margc++] = "net.kdt.pojavlaunch.PLaunchApp";
- }
+ margv[margc++] = "-cp";
+ margv[margc++] = classpath;
+ margv[margc++] = "net.kdt.pojavlaunch.PLaunchApp";
- JLI_Launch_func *pJLI_Launch =
- (JLI_Launch_func *)dlsym(libjli, "JLI_Launch");
+ margv[margc++] = (char *)username.UTF8String;
+ margv[margc++] = (char *)selectedVersion.UTF8String;
+ margv[margc++] = (char *)[NSString stringWithFormat:@"%dx%d", width, height].UTF8String;
+
+ pJLI_Launch = (JLI_Launch_func *)dlsym(libjli, "JLI_Launch");
if (NULL == pJLI_Launch) {
regLog("[Init] JLI_Launch = NULL");
return -2;
}
- // Free unused char arrays
- free(librarySym);
- free(multidir_char);
-
regLog("[Init] Calling JLI_Launch");
+
/*
for (int i = 0; i < margc; i++) {
- regLog("arg[%d] = %s", i, margv[i]);
+ debugLog("Arg=%s", margv[i]);
}
*/
- int targc = started ? argc : margc;
- char **targv = started ? argv : margv;
-
- if (!started) {
- started = YES;
- }
-
- for (int i = 0; i < targc; i++) {
- debugLog("Arg=%s", targv[i]);
- }
-
- return pJLI_Launch(targc, targv,
+
+ return pJLI_Launch(margc, margv,
0, NULL, // sizeof(const_jargs) / sizeof(char *), const_jargs,
0, NULL, // sizeof(const_appclasspath) / sizeof(char *), const_appclasspath,
- FULL_VERSION,
- DOT_VERSION,
- const_progname, // (const_progname != NULL) ? const_progname : *margv,
- const_launcher, // (const_launcher != NULL) ? const_launcher : *margv,
- (const_jargs != NULL) ? JNI_TRUE : JNI_FALSE,
- const_cpwildcard, const_javaw, const_ergo_class);
+ // PojavLancher: fixme: are these wrong?
+ "1.8.0-internal",
+ "1.8",
+
+ "java", "openjdk",
+ /* (const_jargs != NULL) ? JNI_TRUE : */ JNI_FALSE,
+ JNI_TRUE, JNI_FALSE, JNI_TRUE);
}
diff --git a/Natives/LauncherPreferences.h b/Natives/LauncherPreferences.h
index 416c6e35..a9d2d15d 100644
--- a/Natives/LauncherPreferences.h
+++ b/Natives/LauncherPreferences.h
@@ -1,5 +1,9 @@
#import
+#define JRE8_HOME_JB @"/usr/lib/jvm/java-8-openjdk"
+#define JRE16_HOME_JB @"/usr/lib/jvm/java-16-openjdk"
+#define JRE17_HOME_JB @"/usr/lib/jvm/java-17-openjdk"
+
void loadPreferences();
id getPreference(NSString* key);
NSMutableDictionary* getDictionary(NSString *type);
diff --git a/Natives/LauncherPreferencesViewController.h b/Natives/LauncherPreferencesViewController.h
index 482e6cea..08d7e687 100644
--- a/Natives/LauncherPreferencesViewController.h
+++ b/Natives/LauncherPreferencesViewController.h
@@ -1,5 +1,10 @@
#import
+#define JRE8_NAME_JB @"Java 8"
+#define JRE16_NAME_JB @"Java 16"
+#define JRE17_NAME_JB @"Java 17"
+#define JRE8_NAME_SB @"Java 8 (sandbox)"
+
@interface LauncherPreferencesViewController : UIViewController
@end
diff --git a/Natives/LauncherPreferencesViewController.m b/Natives/LauncherPreferencesViewController.m
index e0b3cbf0..9b5dc58d 100644
--- a/Natives/LauncherPreferencesViewController.m
+++ b/Natives/LauncherPreferencesViewController.m
@@ -95,14 +95,7 @@ UIScrollView *scrollView;
NSDictionary *rendererDict;
-NSString *java8jben = @"Java 8";
-NSString *java16jben = @"Java 16";
-NSString *java17jben = @"Java 17";
-NSString *java8 = @"Java 8 (sandbox)";
-NSString *libsjava8jben = @"/usr/lib/jvm/java-8-openjdk";
-NSString *libsjava16jben = @"/usr/lib/jvm/java-16-openjdk";
-NSString *libsjava17jben = @"/usr/lib/jvm/java-17-openjdk";
-NSString *libsjava8;
+NSString *JRE8_HOME_SB;
int tempIndex;
@@ -277,17 +270,17 @@ int tempIndex;
jhomeTextField.delegate = self;
jhomeTextField.placeholder = @"Override Java path...";
- libsjava8 = [NSString stringWithFormat:@"%s/jre8", getenv("POJAV_HOME")];
+ JRE8_HOME_SB = [NSString stringWithFormat:@"%s/jre8", getenv("POJAV_HOME")];
if(getenv("POJAV_DETECTEDJB")) {
- if ([getPreference(@"java_home") isEqualToString:libsjava8jben]) {
- jhomeTextField.text = java8jben;
- } else if ([getPreference(@"java_home") isEqualToString:libsjava16jben]) {
- jhomeTextField.text = java16jben;
- } else if ([getPreference(@"java_home") isEqualToString:libsjava17jben]) {
- jhomeTextField.text = java17jben;
+ if ([getPreference(@"java_home") isEqualToString:JRE8_HOME_JB]) {
+ jhomeTextField.text = JRE8_NAME_JB;
+ } else if ([getPreference(@"java_home") isEqualToString:JRE16_HOME_JB]) {
+ jhomeTextField.text = JRE16_NAME_JB;
+ } else if ([getPreference(@"java_home") isEqualToString:JRE17_HOME_JB]) {
+ jhomeTextField.text = JRE17_NAME_JB;
}
} else {
- jhomeTextField.text = java8;
+ jhomeTextField.text = JRE8_NAME_SB;
}
jhomeTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
@@ -295,17 +288,17 @@ int tempIndex;
[tableView addSubview:jhomeTextField];
jhomeList = [[NSMutableArray alloc] init];
- if ([[NSFileManager defaultManager] fileExistsAtPath:libsjava8jben]) {
- [jhomeList addObject:java8jben];
+ if ([[NSFileManager defaultManager] fileExistsAtPath:JRE8_HOME_JB]) {
+ [jhomeList addObject:JRE8_NAME_JB];
}
- if ([[NSFileManager defaultManager] fileExistsAtPath:libsjava16jben]) {
- [jhomeList addObject:java16jben];
+ if ([[NSFileManager defaultManager] fileExistsAtPath:JRE16_HOME_JB]) {
+ [jhomeList addObject:JRE16_NAME_JB];
}
- if ([[NSFileManager defaultManager] fileExistsAtPath:libsjava17jben]) {
- [jhomeList addObject:java17jben];
+ if ([[NSFileManager defaultManager] fileExistsAtPath:JRE17_HOME_JB]) {
+ [jhomeList addObject:JRE17_NAME_JB];
}
- if ([[NSFileManager defaultManager] fileExistsAtPath:libsjava8]) {
- [jhomeList addObject:java8];
+ if ([[NSFileManager defaultManager] fileExistsAtPath:JRE8_HOME_SB]) {
+ [jhomeList addObject:JRE8_NAME_SB];
}
jhomePickerView = [[UIPickerView alloc] init];
@@ -642,20 +635,20 @@ int tempIndex;
setPreference(@"renderer", rendererDict[textField.text]);
setenv("POJAV_RENDERER", [getPreference(@"renderer") UTF8String], 1);
} else if (textField.tag == TAG_JHOME) {
- if ([textField.text isEqualToString:java8jben]) {
- setPreference(@"java_home", libsjava8jben);
- setenv("JAVA_HOME", [libsjava8jben cStringUsingEncoding:NSUTF8StringEncoding], 1);
- } else if ([textField.text isEqualToString:java16jben]) {
- setPreference(@"java_home", libsjava16jben);
- setenv("JAVA_HOME", [libsjava16jben cStringUsingEncoding:NSUTF8StringEncoding], 1);
- } else if ([textField.text isEqualToString:java17jben]) {
- setPreference(@"java_home", libsjava17jben);
- setenv("JAVA_HOME", [libsjava17jben cStringUsingEncoding:NSUTF8StringEncoding], 1);
- } else if ([textField.text isEqualToString:java8]) {
- setPreference(@"java_home", libsjava8);
- setenv("JAVA_HOME", [libsjava8 cStringUsingEncoding:NSUTF8StringEncoding], 1);
+ if ([textField.text isEqualToString:JRE8_NAME_JB]) {
+ setPreference(@"java_home", JRE8_HOME_JB);
+ setenv("JAVA_HOME", [JRE8_HOME_JB cStringUsingEncoding:NSUTF8StringEncoding], 1);
+ } else if ([textField.text isEqualToString:JRE16_NAME_JB]) {
+ setPreference(@"java_home", JRE16_HOME_JB);
+ setenv("JAVA_HOME", [JRE16_HOME_JB cStringUsingEncoding:NSUTF8StringEncoding], 1);
+ } else if ([textField.text isEqualToString:JRE17_NAME_JB]) {
+ setPreference(@"java_home", JRE17_HOME_JB);
+ setenv("JAVA_HOME", [JRE17_HOME_JB cStringUsingEncoding:NSUTF8StringEncoding], 1);
+ } else if ([textField.text isEqualToString:JRE8_NAME_SB]) {
+ setPreference(@"java_home", JRE8_HOME_SB);
+ setenv("JAVA_HOME", [JRE8_HOME_SB cStringUsingEncoding:NSUTF8StringEncoding], 1);
}
- if (![textField.text containsString:java8jben] && ![textField.text containsString:java8] && [getPreference(@"java_warn") boolValue] == YES) {
+ if (![textField.text containsString:JRE8_NAME_JB] && ![textField.text containsString:JRE8_NAME_SB] && [getPreference(@"java_warn") boolValue] == YES) {
UIAlertController *javaAlert = [UIAlertController alertControllerWithTitle:@"Java version is not Java 8" message:@"Minecraft versions below 1.6, modded below 1.16.4, and the mod installer will not work unless you have Java 8 installed on your device."preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
[self presentViewController:javaAlert animated:YES completion:nil];
diff --git a/Natives/MinecraftDownloader.m b/Natives/MinecraftDownloader.m
index c407b16f..1cd2f1fb 100644
--- a/Natives/MinecraftDownloader.m
+++ b/Natives/MinecraftDownloader.m
@@ -135,7 +135,7 @@ static AFURLSessionManager* manager;
//Log.d(APP_NAME, "Library " + libName + ": Replaced version " +
//libName.substring(libName.lastIndexOf(":") + 1) + " with " +
//libAddedName.substring(libAddedName.lastIndexOf(":") + 1));
- inheritsFrom[@"libraries"][i] = lib;
+ inheritsFrom[@"libraries"][i] = lib;
i = -1;
break;
}
@@ -284,9 +284,12 @@ static AFURLSessionManager* manager;
+ (void)tweakVersionJson:(NSMutableDictionary *)json {
// Exclude some libraries
for (NSMutableDictionary *library in json[@"libraries"]) {
- if ([library[@"name"] hasPrefix:@"org.lwjgl"]) {
- library[@"skip"] = @(YES);
- }
+ library[@"skip"] = @(
+ // Exclude platform-dependant libraries
+ library[@"downloads"][@"classifiers"] != nil ||
+ // Exclude LWJGL libraries
+ [library[@"name"] hasPrefix:@"org.lwjgl"]
+ );
}
// Add the client as a library
diff --git a/Natives/SurfaceViewController.m b/Natives/SurfaceViewController.m
index 63ad9107..679531d1 100644
--- a/Natives/SurfaceViewController.m
+++ b/Natives/SurfaceViewController.m
@@ -1,10 +1,12 @@
#import
+#import "JavaLauncher.h"
#import "LauncherPreferences.h"
#import "SurfaceViewController.h"
#import "egl_bridge.h"
#import "ios_uikit_bridge.h"
+#import "authenticator/BaseAuthenticator.h"
#import "customcontrols/ControlButton.h"
#import "customcontrols/ControlDrawer.h"
#import "customcontrols/ControlSubButton.h"
@@ -239,7 +241,7 @@ const void * _CGDataProviderGetBytePointerCallbackOSMESA(void *info) {
self.inputView.lastPosition = 20;
[self.inputView addTarget:self action:@selector(inputViewDidChange) forControlEvents:UIControlEventEditingChanged];
- NSString *controlFilePath = [NSString stringWithFormat:@"%s/%@", getenv("POJAV_PATH_CONTROL"), (NSString *)getPreference(@"default_ctrl")];
+ NSString *controlFilePath = [NSString stringWithFormat:@"%s/controlmap/%@", getenv("POJAV_HOME"), (NSString *)getPreference(@"default_ctrl")];
NSError *cc_error;
NSString *cc_data = [NSString stringWithContentsOfFile:controlFilePath encoding:NSUTF8StringEncoding error:&cc_error];
@@ -314,7 +316,10 @@ const void * _CGDataProviderGetBytePointerCallbackOSMESA(void *info) {
// [self setPreferredFramesPerSecond:1000];
- callback_SurfaceViewController_launchMinecraft(savedWidth * resolutionScale, savedHeight * resolutionScale);
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ launchJVM(BaseAuthenticator.current.authData[@"username"], getPreference(@"selected_version"), savedWidth * resolutionScale, savedHeight * resolutionScale);
+ });
+ //callback_SurfaceViewController_launchMinecraft(savedWidth * resolutionScale, savedHeight * resolutionScale);
}
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
diff --git a/Natives/authenticator/BaseAuthenticator.m b/Natives/authenticator/BaseAuthenticator.m
index 93345015..f56291e6 100644
--- a/Natives/authenticator/BaseAuthenticator.m
+++ b/Natives/authenticator/BaseAuthenticator.m
@@ -59,17 +59,12 @@ static BaseAuthenticator *current = nil;
[self.authData removeObjectForKey:@"oldusername"];
- NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self.authData options:NSJSONWritingPrettyPrinted error:&error];
- if (jsonData == nil) {
- showDialog(viewController, @"Error while converting to JSON", error.localizedDescription);
- return NO;
- }
+ error = saveJSONToFile(self.authData, newPath);
- BOOL success = [jsonData writeToFile:newPath options:NSDataWritingAtomic error:&error];
- if (!success) {
+ if (error != nil) {
showDialog(viewController, @"Error while saving file", error.localizedDescription);
}
- return success;
+ return error == nil;
}
@end
diff --git a/Natives/customcontrols/CustomControlsUtils.m b/Natives/customcontrols/CustomControlsUtils.m
index e59cb7c5..fbc11fe6 100644
--- a/Natives/customcontrols/CustomControlsUtils.m
+++ b/Natives/customcontrols/CustomControlsUtils.m
@@ -287,7 +287,7 @@ void generateAndSaveDefaultControl() {
BTN_RECT
)];
NSOutputStream *os = [[NSOutputStream alloc] initToFileAtPath:
- [@(getenv("POJAV_PATH_CONTROL")) stringByAppendingString:@"/default.json"] append:NO];
+ [NSString stringWithFormat:@"%s/controlmap/default.json", getenv("POJAV_HOME")] append:NO];
[os open];
[NSJSONSerialization writeJSONObject:dict toStream:os options:NSJSONWritingPrettyPrinted error:nil];
[os close];
diff --git a/Natives/en.lproj/Localizable.strings b/Natives/en.lproj/Localizable.strings
index 035d8127..b8b15747 100644
--- a/Natives/en.lproj/Localizable.strings
+++ b/Natives/en.lproj/Localizable.strings
@@ -3,6 +3,8 @@
StringLocalization
*/
+"init.migrateDir" = "The PojavLauncher data directory is now %@. All of your existing data has been moved to the new location.";
+
"login.error.username.outOfRange" = "Username must be at least 3 characters and maximum 16 characters";
"login.alert.title" = "Login";
diff --git a/Natives/input_bridge_v3.m b/Natives/input_bridge_v3.m
index b5501d3a..bdb852e7 100644
--- a/Natives/input_bridge_v3.m
+++ b/Natives/input_bridge_v3.m
@@ -38,8 +38,8 @@ typedef void GLFW_invoke_WindowPos_func(void* window, int x, int y);
CGFloat grabCursorX, grabCursorY, lastCursorX, lastCursorY;
-jclass inputBridgeClass_ANDROID, inputBridgeClass_JRE;
-jmethodID inputBridgeMethod_ANDROID, inputBridgeMethod_JRE;
+jclass inputBridgeClass_ANDROID;
+jmethodID inputBridgeMethod_ANDROID;
jclass uikitBridgeClass;
jmethodID uikitBridgeTouchMethod;
@@ -47,16 +47,12 @@ jmethodID uikitBridgeTouchMethod;
// JNI_OnLoad
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
runtimeJavaVMPtr = vm;
- (*vm)->GetEnv(vm, (void**) &runtimeJNIEnvPtr_JRE, JNI_VERSION_1_4);
-
- isGrabbing = JNI_FALSE;
-
return JNI_VERSION_1_4;
}
// Should be?
void JNI_OnUnload(JavaVM* vm, void* reserved) {
- runtimeJNIEnvPtr_JRE = NULL;
+ runtimeJNIEnvPtr = NULL;
}
#define ADD_CALLBACK_WWIN(NAME) \
@@ -81,29 +77,29 @@ ADD_CALLBACK_WWIN(WindowPos);
#undef ADD_CALLBACK_WWIN
void getJavaInputBridge(jclass* clazz, jmethodID* method) {
- debugLog("Debug: Initializing input bridge, method.isNull=%d, jnienv.isNull=%d\n", *method == NULL, runtimeJNIEnvPtr_ANDROID == NULL);
- if (*method == NULL && runtimeJNIEnvPtr_ANDROID != NULL) {
- *clazz = (*runtimeJNIEnvPtr_ANDROID)->FindClass(runtimeJNIEnvPtr_ANDROID, "org/lwjgl/glfw/CallbackBridge");
+ debugLog("Debug: Initializing input bridge, method.isNull=%d, jnienv.isNull=%d\n", *method == NULL, runtimeJNIEnvPtr == NULL);
+ if (*method == NULL && runtimeJNIEnvPtr != NULL) {
+ *clazz = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "org/lwjgl/glfw/CallbackBridge");
assert(*clazz != NULL);
- *method = (*runtimeJNIEnvPtr_ANDROID)->GetStaticMethodID(runtimeJNIEnvPtr_ANDROID, *clazz, "receiveCallback", "(IFFII)V");
+ *method = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, *clazz, "receiveCallback", "(IFFII)V");
assert(*method != NULL);
}
}
void sendData(int type, CGFloat i1, CGFloat i2, int i3, int i4) {
- if (runtimeJNIEnvPtr_ANDROID == NULL) {
- (*runtimeJavaVMPtr)->GetEnv(runtimeJavaVMPtr, (void**) &runtimeJNIEnvPtr_ANDROID, JNI_VERSION_1_4);
+ if (inputBridgeMethod_ANDROID == NULL) {
+ (*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, &runtimeJNIEnvPtr, NULL);
getJavaInputBridge(&inputBridgeClass_ANDROID, &inputBridgeMethod_ANDROID);
}
- debugLog("Debug: Send data, jnienv.isNull=%d\n", runtimeJNIEnvPtr_ANDROID == NULL);
- if (runtimeJNIEnvPtr_ANDROID == NULL) {
+ debugLog("Debug: Send data, jnienv.isNull=%d\n", runtimeJNIEnvPtr == NULL);
+ if (runtimeJNIEnvPtr == NULL) {
debugLog("BUG: Input is ready but thread is not attached yet.");
return;
}
// FIXME: should we send double instead of float?
- (*runtimeJNIEnvPtr_ANDROID)->CallStaticVoidMethod(
- runtimeJNIEnvPtr_ANDROID,
+ (*runtimeJNIEnvPtr)->CallStaticVoidMethod(
+ runtimeJNIEnvPtr,
inputBridgeClass_ANDROID,
inputBridgeMethod_ANDROID,
type,
@@ -115,13 +111,13 @@ void closeGLFWWindow() {
NSLog(@"Closing GLFW window");
/*
- jclass glfwClazz = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "org/lwjgl/glfw/GLFW");
+ jclass glfwClazz = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "org/lwjgl/glfw/GLFW");
assert(glfwClazz != NULL);
- jmethodID glfwMethod = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, glfwMethod, "glfwSetWindowShouldClose", "(JZ)V");
+ jmethodID glfwMethod = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, glfwMethod, "glfwSetWindowShouldClose", "(JZ)V");
assert(glfwMethod != NULL);
- (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
- runtimeJNIEnvPtr_JRE,
+ (*runtimeJNIEnvPtr)->CallStaticVoidMethod(
+ runtimeJNIEnvPtr,
glfwClazz, glfwMethod,
(jlong) showingWindow, JNI_TRUE
);
@@ -129,63 +125,51 @@ void closeGLFWWindow() {
exit(-1);
}
-void callback_LauncherViewController_installMinecraft(char* versionPath) {
- // Because UI init after JVM init, this should not be null
- assert(runtimeJNIEnvPtr_JRE != NULL);
-
- if (!uikitBridgeClass) {
- uikitBridgeClass = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "net/kdt/pojavlaunch/uikit/UIKit");
- assert(uikitBridgeClass != NULL);
- }
-
- jstring versionPathStr = (*runtimeJNIEnvPtr_JRE)->NewStringUTF(runtimeJNIEnvPtr_JRE, versionPath);
-
- jmethodID method = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, uikitBridgeClass, "callback_LauncherViewController_installMinecraft", "(Ljava/lang/String;)V");
- assert(method != NULL);
- (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
- runtimeJNIEnvPtr_JRE,
- uikitBridgeClass, method,
- versionPathStr
- );
-}
-
+/*
void callback_SurfaceViewController_launchMinecraft(int width, int height) {
debugLog("Received SurfaceViewController callback, width=%d, height=%d\n", width, height);
// Because UI init after JVM init, this should not be null
- assert(runtimeJNIEnvPtr_JRE != NULL);
+ assert(runtimeJNIEnvPtr != NULL);
if (!uikitBridgeClass) {
- uikitBridgeClass = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "net/kdt/pojavlaunch/uikit/UIKit");
+ uikitBridgeClass = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "net/kdt/pojavlaunch/uikit/UIKit");
assert(uikitBridgeClass != NULL);
}
- jstring rendererLibStr = (*runtimeJNIEnvPtr_JRE)->NewStringUTF(runtimeJNIEnvPtr_JRE, getenv("POJAV_RENDERER"));
+ jstring rendererLibStr = (*runtimeJNIEnvPtr)->NewStringUTF(runtimeJNIEnvPtr, getenv("POJAV_RENDERER"));
- jmethodID method = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, uikitBridgeClass, "callback_SurfaceViewController_launchMinecraft", "(IILjava/lang/String;)V");
+ jmethodID method = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, uikitBridgeClass, "callback_SurfaceViewController_launchMinecraft", "(IILjava/lang/String;)V");
assert(method != NULL);
- (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
- runtimeJNIEnvPtr_JRE,
+ (*runtimeJNIEnvPtr)->CallStaticVoidMethod(
+ runtimeJNIEnvPtr,
uikitBridgeClass, method,
width, height,
rendererLibStr
);
}
+*/
void callback_SurfaceViewController_onTouch(int event, CGFloat x, CGFloat y) {
+ if (!isInputReady) return;
+
+ if (!runtimeJNIEnvPtr) {
+ (*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, &runtimeJNIEnvPtr, NULL);
+ }
+
if (!uikitBridgeClass) {
- uikitBridgeClass = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "net/kdt/pojavlaunch/uikit/UIKit");
+ uikitBridgeClass = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "net/kdt/pojavlaunch/uikit/UIKit");
assert(uikitBridgeClass != NULL);
}
-
+
if (!uikitBridgeTouchMethod) {
- uikitBridgeTouchMethod = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, uikitBridgeClass, "callback_SurfaceViewController_onTouch", "(IFF)V");
+ uikitBridgeTouchMethod = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, uikitBridgeClass, "callback_SurfaceViewController_onTouch", "(IFF)V");
assert(uikitBridgeTouchMethod != NULL);
}
-
- (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
- runtimeJNIEnvPtr_JRE,
+
+ (*runtimeJNIEnvPtr)->CallStaticVoidMethod(
+ runtimeJNIEnvPtr,
uikitBridgeClass, uikitBridgeTouchMethod,
event, (jfloat)x, (jfloat)y
);
@@ -239,7 +223,9 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetInputRead
#ifdef DEBUG
LOGD("Debug: Changing input state, isReady=%d, isUseStackQueueCall=%d\n", inputReady, isUseStackQueueCall);
#endif
+
isInputReady = inputReady;
+
return isUseStackQueueCall;
}
@@ -446,13 +432,13 @@ void CallbackBridge_setWindowAttrib(int attrib, int value) {
return; // nothing to do yet
}
- jclass glfwClazz = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "org/lwjgl/glfw/GLFW");
+ jclass glfwClazz = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "org/lwjgl/glfw/GLFW");
assert(glfwClazz != NULL);
- jmethodID glfwMethod = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, glfwClazz, "glfwSetWindowAttrib", "(JII)V");
+ jmethodID glfwMethod = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, glfwClazz, "glfwSetWindowAttrib", "(JII)V");
assert(glfwMethod != NULL);
- (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
- runtimeJNIEnvPtr_JRE,
+ (*runtimeJNIEnvPtr)->CallStaticVoidMethod(
+ runtimeJNIEnvPtr,
glfwClazz, glfwMethod,
(jlong) showingWindow, attrib, value
);
diff --git a/Natives/ios_uikit_bridge.m b/Natives/ios_uikit_bridge.m
index bca8db6e..60b4365c 100644
--- a/Natives/ios_uikit_bridge.m
+++ b/Natives/ios_uikit_bridge.m
@@ -105,20 +105,20 @@ jstring UIKit_accessClipboard(JNIEnv* env, jint action, jstring copySrc) {
}
void UIKit_launchJarFile(const char* filepath) {
- jclass uikitBridgeClass = (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "net/kdt/pojavlaunch/uikit/UIKit");
+ jclass uikitBridgeClass = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "net/kdt/pojavlaunch/uikit/UIKit");
assert(uikitBridgeClass != NULL);
- jstring filepathStr = (*runtimeJNIEnvPtr_JRE)->NewStringUTF(runtimeJNIEnvPtr_JRE, filepath);
- jmethodID method = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, uikitBridgeClass, "callback_JavaGUIViewController_launchJarFile", "(Ljava/lang/String;II)V");
+ jstring filepathStr = (*runtimeJNIEnvPtr)->NewStringUTF(runtimeJNIEnvPtr, filepath);
+ jmethodID method = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, uikitBridgeClass, "callback_JavaGUIViewController_launchJarFile", "(Ljava/lang/String;II)V");
assert(method != NULL);
- (*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
- runtimeJNIEnvPtr_JRE,
+ (*runtimeJNIEnvPtr)->CallStaticVoidMethod(
+ runtimeJNIEnvPtr,
uikitBridgeClass, method,
filepathStr,
savedWidth, savedHeight
);
- (*runtimeJNIEnvPtr_JRE)->DeleteLocalRef(runtimeJNIEnvPtr_JRE, filepathStr);
+ (*runtimeJNIEnvPtr)->DeleteLocalRef(runtimeJNIEnvPtr, filepathStr);
}
void UIKit_launchMinecraftSurfaceVC() {
diff --git a/Natives/main.m b/Natives/main.m
index 14dcc90f..bfa6a7a2 100644
--- a/Natives/main.m
+++ b/Natives/main.m
@@ -1,23 +1,280 @@
+#import
+
+#import "AppDelegate.h"
+#import "customcontrols/CustomControlsUtils.h"
+#import "LauncherPreferences.h"
+#import "LauncherPreferencesViewController.h"
+
#include
+#include
#include
#include
#include
+#include
+#include
+#include
+#include
#include
#include "JavaLauncher.h"
+#include "log.h"
+#include "utils.h"
+
+#if CONFIG_RELEASE == 1
+# define CONFIG_TYPE "release"
+#else
+# define CONFIG_TYPE "debug"
+#endif
+
+#ifndef CONFIG_COMMIT
+# define CONFIG_COMMIT unspecified
+#endif
+
+#define fm NSFileManager.defaultManager
+
+void init_loadCustomEnv() {
+ /* Define default env */
+
+ // I accidentally patched a bit wrong, the value should be a path containing libawt_xawt.dylib, but here is libawt.dylib path (no need to exist)
+ setenv("JAVA_AWT_PATH", [NSString stringWithFormat:@"%s/Frameworks/libawt.dylib", getenv("BUNDLE_PATH")].UTF8String, 1);
+
+ // Disable overloaded functions hack for Minecraft 1.17+
+ setenv("LIBGL_NOINTOVLHACK", "1", 1);
+
+ // Override OpenGL version to 4.1 for Zink
+ setenv("MESA_GL_VERSION_OVERRIDE", "4.1", 1);
+
+ /* Load custom env */
+ FILE *envFile = fopen([NSString stringWithFormat:@"%s/custom_env.txt", getenv("POJAV_HOME")].UTF8String, "r");
+
+ regLog("[Pre-init] Reading custom environment variables (custom_env.txt), opened=%d\n", envFile != NULL);
+
+ if (envFile) {
+ char *line = NULL;
+ size_t len = 0;
+ ssize_t read;
+ while ((read = getline(&line, &len, envFile)) != -1) {
+ if (line[0] == '#' || line[0] == '\n') continue;
+ if (line[read-1] == '\n') {
+ line[read-1] = '\0';
+ }
+ if (strchr(line, '=') != NULL) {
+ regLog("[Pre-init] Added custom env: %s", line);
+ setenv(strtok(line, "="), strtok(NULL, "="), 1);
+ } else {
+ regLog("[Pre-init] Warning: skipped empty value custom env: %s", line);
+ }
+ }
+ fclose(envFile);
+ }
+}
+
+void init_logDeviceAndVer(char *argument) {
+ struct utsname systemInfo;
+ uname(&systemInfo);
+ // Hardware + software
+ const char *deviceHardware = systemInfo.machine;
+ const char *deviceSoftware = [[[UIDevice currentDevice] systemVersion] cStringUsingEncoding:NSUTF8StringEncoding];
+
+ // Jailbreak
+ const char *jbStrap;
+ if (strncmp(argument, "/Applications", 13) == 0) {
+ if ([[NSFileManager defaultManager] fileExistsAtPath:@"/.procursus_strapped"]) {
+ jbStrap = "Procursus";
+ } else {
+ jbStrap = "Other";
+ }
+ regLog("[Pre-Init] %s with iOS %s (%s)", deviceHardware, deviceSoftware, jbStrap);
+ } else {
+ regLog("[Pre-Init] %s with iOS %s", deviceHardware, deviceSoftware);
+ }
+
+ // PojavLauncher version
+ regLog("[Pre-Init] PojavLauncher version: %s - %s", CONFIG_TYPE, CONFIG_COMMIT);
+
+ setenv("POJAV_DETECTEDHW", deviceHardware, 1);
+ setenv("POJAV_DETECTEDSW", deviceSoftware, 1);
+ if (strncmp(argument, "/Applications", 13) == 0) {
+ setenv("POJAV_DETECTEDJB", jbStrap, 1);
+ }
+}
+
+void init_migrateDirIfNecessary() {
+ NSString *completeFile = @"/var/mobile/Documents/.pojavlauncher/migration_complete";
+ NSString *oldDir = @"/var/mobile/Documents/.pojavlauncher";
+ if ([fm fileExistsAtPath:oldDir] && ![fm fileExistsAtPath:completeFile]) {
+ NSString *newDir = @"/usr/share/pojavlauncher";
+ if (@available(iOS 15, *)) {
+ newDir = @"/private/preboot/procursus/usr/share/pojavlauncher";
+ }
+
+ [fm moveItemAtPath:oldDir toPath:newDir error:nil];
+ [fm createSymbolicLinkAtPath:oldDir withDestinationPath:newDir error:nil];
+
+ NSString *message = [NSString stringWithFormat:NSLocalizedString(@"init.migrateDir", nil), newDir];
+ [message writeToFile:completeFile atomically:YES encoding:NSUTF8StringEncoding error:nil];
+ }
+}
+
+void init_migrateToPlist(char* prefKey, char* filename) {
+ // NSString *readmeStr = @"#README - this file has been merged into launcher_preferences.plist";
+ NSError *error;
+ NSString *str, *path_str;
+
+ // overrideargs.txt
+ path_str = [NSString stringWithFormat:@"%s/%s", getenv("POJAV_HOME"), filename];
+ str = [NSString stringWithContentsOfFile:path_str encoding:NSUTF8StringEncoding error:&error];
+ if (error == nil && ![str hasPrefix:@"#README"]) {
+ setPreference(@(prefKey), str);
+ [@"#README - this file has been merged into launcher_preferences.plist" writeToFile:path_str atomically:YES encoding:NSUTF8StringEncoding error:nil];
+ }
+}
+
+void init_redirectStdio() {
+ regLog("[Pre-init] Starting logging STDIO to latestlog.txt\n");
+
+ NSString *currName = [@(getenv("POJAV_HOME")) stringByAppendingPathComponent:@"latestlog.txt"];
+ NSString *oldName = [@(getenv("POJAV_HOME")) stringByAppendingPathComponent:@"latestlog.old.txt"];
+ [fm removeItemAtPath:oldName error:nil];
+ [fm moveItemAtPath:currName toPath:oldName error:nil];
+
+ [fm createFileAtPath:currName contents:nil attributes:nil];
+ NSFileHandle *file = [NSFileHandle fileHandleForWritingAtPath:currName];
+
+ if (!file) {
+ NSLog(@"[Pre-init] Error: failed to open %@", currName);
+ assert(0 && "Failed to open latestlog.txt. Check oslog for more details.");
+ }
+
+ setvbuf(stdout, 0, _IOLBF, 0); // make stdout line-buffered
+ setvbuf(stderr, 0, _IONBF, 0); // make stderr unbuffered
+
+ /* create the pipe and redirect stdout and stderr */
+ static int pfd[2];
+ pipe(pfd);
+ dup2(pfd[1], 1);
+ dup2(pfd[1], 2);
+
+ /* create the logging thread */
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ static BOOL filteredSessionID;
+ ssize_t rsize;
+ char buf[2048];
+ while((rsize = read(pfd[0], buf, sizeof(buf)-1)) > 0) {
+ // Filter out Session ID here
+ int index;
+ if (!filteredSessionID) {
+ char *sessionStr = strstr(buf, "(Session ID is ");
+ if (sessionStr) {
+ char *censorStr = "(Session ID is )\n\0";
+ strcpy(sessionStr, censorStr);
+ rsize = strlen(buf);
+ filteredSessionID = true;
+ }
+ }
+ [file writeData:[NSData dataWithBytes:buf length:rsize]];
+ [file synchronizeFile];
+ }
+ [file closeFile];
+ });
+}
+
+void init_setupCustomControls() {
+ NSString *controlPath = [@(getenv("POJAV_HOME")) stringByAppendingPathComponent:@"controlmap"];
+ [fm createDirectoryAtPath:controlPath withIntermediateDirectories:NO attributes:nil error:nil];
+ generateAndSaveDefaultControl();
+}
+
+void init_setupLauncherProfiles() {
+ NSString *file = [@(getenv("POJAV_GAME_DIR")) stringByAppendingPathComponent:@"launcher_profiles.json"];
+ if (![fm fileExistsAtPath:file]) {
+ NSDictionary *dict = @{
+ @"profiles": @{
+ @"(Default)": @{
+ @"name": @"(Default)",
+ @"lastVersionId": @"Unknown"
+ }
+ },
+ @"selectedProfile": @"(Default)"
+ };
+ saveJSONToFile(dict, file);
+ }
+}
+
+void init_setupMultiDir() {
+ NSString *multidir = getPreference(@"game_directory");
+ if (multidir.length == 0) {
+ multidir = @"default";
+ setPreference(@"game_directory", multidir);
+ NSLog(@"[Pre-init] MULTI_DIR environment variable was not set. Defaulting to %@ for future use.\n", multidir);
+ } else {
+ NSLog(@"[Pre-init] Restored preference: MULTI_DIR is set to %@\n", multidir);
+ }
+
+ NSString *lasmPath = [NSString stringWithFormat:@"%s/Library/Application Support/minecraft", getenv("POJAV_HOME")]; //libr
+ NSString *multidirPath = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), multidir];
+
+ [fm createDirectoryAtPath:multidirPath withIntermediateDirectories:YES attributes:nil error:nil];
+ [fm removeItemAtPath:lasmPath error:nil];
+ [fm createSymbolicLinkAtPath:lasmPath withDestinationPath:multidirPath error:nil];
+ setenv("POJAV_GAME_DIR", lasmPath.UTF8String, 1);
+
+ if (0 == access("/var/mobile/Documents/minecraft", F_OK)) {
+ [fm moveItemAtPath:@"/var/mobile/Documents/minecraft" toPath:multidir error:nil];
+ regLog("[Pre-init] Migrated old minecraft folder to new location.");
+ }
+
+ if (0 == access("/var/mobile/Documents/Library", F_OK)) {
+ remove("/var/mobile/Documents/Library");
+ }
+
+ [fm changeCurrentDirectoryPath:lasmPath];
+}
int main(int argc, char * argv[]) {
-/*
- if (getppid() != 1) {
- // Not running from launchd, so UI won't work.
- printf("ERROR: ppid was %d\n", getppid());
- printf("ERROR: UIKit is unavailable when run on command line! Please run from home screen instead. If you didn't see PojavLauncher on home screen, run this command:\n");
- printf("uicache -p /Applications/PojavLauncher.app\n");
+ if (pJLI_Launch) {
+ return pJLI_Launch(argc, argv,
+ 0, NULL, // sizeof(const_jargs) / sizeof(char *), const_jargs,
+ 0, NULL, // sizeof(const_appclasspath) / sizeof(char *), const_appclasspath,
+ // PojavLancher: fixme: are these wrong?
+ "1.8.0-internal",
+ "1.8",
- return -1;
+ "java", "openjdk",
+ /* (const_jargs != NULL) ? JNI_TRUE : */ JNI_FALSE,
+ JNI_TRUE, JNI_FALSE, JNI_TRUE);
}
-*/
- launchJVM(argc, argv);
+ init_migrateDirIfNecessary();
- return 0;
+ setenv("BUNDLE_PATH", dirname(argv[0]), 1);
+
+ // Are we running on a jailbroken environment?
+ if (strncmp(argv[0], "/Applications", 13) == 0) {
+ setenv("HOME", "/usr/share", 1);
+ setenv("OLD_POJAV_HOME", "/var/mobile/Documents/.pojavlauncher", 1);
+ setenv("POJAV_HOME", "/usr/share/pojavlauncher", 1);
+ } else {
+ setenv("POJAV_HOME", [NSString stringWithFormat:@"%s/Documents", getenv("HOME")].UTF8String, 1);
+
+ init_hookFunctions();
+ }
+
+ [fm createDirectoryAtPath:@(getenv("POJAV_HOME")) withIntermediateDirectories:NO attributes:nil error:nil];
+
+ init_redirectStdio();
+ init_logDeviceAndVer(argv[0]);
+
+ init_loadCustomEnv();
+ loadPreferences();
+ init_setupMultiDir();
+ init_setupLauncherProfiles();
+
+ init_setupCustomControls();
+
+ init_migrateToPlist("selected_version", "config_ver.txt");
+ init_migrateToPlist("java_args", "overrideargs.txt");
+
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
}
diff --git a/Natives/main_hook.m b/Natives/main_hook.m
new file mode 100644
index 00000000..c2b70f4e
--- /dev/null
+++ b/Natives/main_hook.m
@@ -0,0 +1,110 @@
+#include
+#include
+#include
+
+#include "external/fishhook/fishhook.h"
+#import "utils.h"
+
+int main(int argc, char * argv[]);
+
+static CFRunLoopRunResult (*orig_CFRunLoopRunInMode)(CFRunLoopMode mode, CFTimeInterval seconds, Boolean returnAfterSourceHandled);
+
+static int (*orig_dladdr)(const void* addr, Dl_info* info);
+static void* (*orig_dlopen)(const char* path, int mode);
+//static void* (*orig_mmap)(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
+static char* (*orig_realpath)(const char *restrict path, char *restrict resolved_path);
+//static void (*orig_sys_icache_invalidate)(void *start, size_t len);
+
+
+int hooked_dladdr(const void* addr, Dl_info* info) {
+ //NSLog(@"hook dladdr(%p, %p)", addr, info);
+ int retVal = orig_dladdr(addr, info);
+ if (addr == main) {
+ //NSLog(@"hooked dladdr");
+ info->dli_fname = getenv("JAVA_EXT_EXECNAME");
+ } else if (retVal != 0) {
+ //NSLog(@"hooked dladdr");
+ char *libname = basename((char *)info->dli_fname);
+ char src[2048], dst[2048];
+ sprintf((char *)src, "%s/Frameworks", getenv("BUNDLE_PATH"));
+ if (0 == strncmp(info->dli_fname, src, strlen(src))) {
+ if (0 == strncmp(libname, "libjli.dylib", 12)) {
+ info->dli_fname = getenv("INTERNAL_JLI_PATH");
+ } else if (0 == strncmp(libname, "libjvm.dylib", 12)) {
+ sprintf((char *)dst, "%s/lib/server/libjvm.dylib", getenv("JAVA_HOME"));
+ info->dli_fname = (char *)dst;
+ }
+ }
+ }
+ //if (retVal) NSLog(@"dli_fname=%s", info->dli_fname);
+ return retVal;
+}
+
+void* hooked_dlopen(const char* path, int mode) {
+ void *handle = orig_dlopen(path, mode);
+ if (handle) {
+ return handle;
+ }
+
+ char src[2048], dst[2048];
+ sprintf((char *)src, "%s/Frameworks", getenv("BUNDLE_PATH"));
+ //NSLog(@"path=%s, src=%s, length=%lu, compare=%d", path, src, strlen(src), strncmp(path, src, strlen(src)));
+ if (!strncmp(path, src, strlen(src))) {
+ //NSLog(@"hooked dlopen %s", path);
+ char *libname = basename((char *)path);
+ sprintf((char *)dst, "%s/%s.framework/%s", src, libname, libname);
+ handle = orig_dlopen(dst, mode);
+ if (handle) {
+ dlerror(); // clear error
+ }
+ }
+
+ return handle;
+}
+
+/*
+void *hooked_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) {
+ NSLog(@"mmap(%p, %ld, %d, %d, %d, %lld)", addr, len, prot, flags, fd, offset);
+
+ if (flags & MAP_JIT) {
+ NSLog(@"'-> Found JIT mmap");
+ //flags &= ~MAP_JIT;
+ }
+
+ // raise(SIGINT);
+ return orig_mmap(addr, len, prot, flags, fd, offset);
+}
+*/
+
+char *hooked_realpath(const char *restrict path, char *restrict resolved_path) {
+ //NSLog(@"hook realpath %s", path);
+ const char *javaHome = getenv("JAVA_HOME");
+ if (0 == strncmp(path, javaHome, strlen(javaHome))) {
+ strcpy(resolved_path, path);
+ return resolved_path;
+ } else {
+ return orig_realpath(path, resolved_path);
+ }
+}
+
+/*
+void hooked_sys_icache_invalidate(void *start, size_t len) {
+ // mprotect(start, 16384, PROT_EXEC | PROT_READ);
+ // NSLog(@"mprotect errno %d", errno);
+ orig_sys_icache_invalidate(start, len);
+}
+*/
+
+void init_hookFunctions() {
+ // if (!started && strncmp(argv[0], "/Applications", 13))
+ // Jailed only: hook some functions for symlinked JRE home dir
+ int retval = rebind_symbols((struct rebinding[3]){
+ {"dladdr", hooked_dladdr, (void *)&orig_dladdr},
+ {"dlopen", hooked_dlopen, (void *)&orig_dlopen},
+ //{"realpath", hooked_realpath, (void *)&orig_realpath},
+ {"realpath$DARWIN_EXTSN", hooked_realpath, (void *)&orig_realpath}
+ //{"mmap", hooked_mmap, (void *)&orig_mmap},
+ //{"sys_icache_invalidate", hooked_sys_icache_invalidate, (void *)&orig_sys_icache_invalidate}
+ }, 3);
+ NSLog(@"hook retval = %d", retval);
+}
diff --git a/Natives/resources/launcher_profiles.json b/Natives/resources/launcher_profiles.json
deleted file mode 100644
index 82c2d176..00000000
--- a/Natives/resources/launcher_profiles.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "profiles": {
- "(Default)": {
- "name": "(Default)",
- "lastVersionId": "Unknown"
- }
- },
- "selectedProfile": "(Default)"
-}
diff --git a/Natives/utils.h b/Natives/utils.h
index 963d8be7..adbe18aa 100644
--- a/Natives/utils.h
+++ b/Natives/utils.h
@@ -44,8 +44,7 @@ UIViewController *viewController;
void* gbuffer; // OSMesa framebuffer
JavaVM* runtimeJavaVMPtr;
-JNIEnv* runtimeJNIEnvPtr_ANDROID;
-JNIEnv* runtimeJNIEnvPtr_JRE;
+JNIEnv* runtimeJNIEnvPtr;
//JNIEnv* dalvikJNIEnvPtr_ANDROID;
//JNIEnv* dalvikJNIEnvPtr_JRE;
@@ -60,8 +59,14 @@ int savedWidth, savedHeight;
BOOL virtualMouseEnabled;
+
+// Init functions
+void init_hookCFRunLoop();
+void init_hookFunctions();
+
+
NSMutableDictionary* parseJSONFromFile(NSString *path);
-NSError* saveJSONToFile(NSMutableDictionary *dict, NSString *path);
+NSError* saveJSONToFile(NSDictionary *dict, NSString *path);
static inline CGFloat clamp(CGFloat x, CGFloat lower, CGFloat upper) {
return fmin(upper, fmax(x, lower));
diff --git a/Natives/utils.m b/Natives/utils.m
index 46e033d3..627d4fb0 100644
--- a/Natives/utils.m
+++ b/Natives/utils.m
@@ -26,7 +26,7 @@ NSMutableDictionary* parseJSONFromFile(NSString *path) {
return dict;
}
-NSError* saveJSONToFile(NSMutableDictionary *dict, NSString *path) {
+NSError* saveJSONToFile(NSDictionary *dict, NSString *path) {
// TODO: handle rename
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error];
@@ -34,7 +34,7 @@ NSError* saveJSONToFile(NSMutableDictionary *dict, NSString *path) {
return error;
}
NSString *jsonStr = [NSString stringWithUTF8String:jsonData.bytes];
- BOOL success = [jsonStr writeToFile:[NSString stringWithFormat:@"%s/accounts/%@.json", getenv("POJAV_HOME"), dict[@"username"]] atomically:YES encoding:NSUTF8StringEncoding error:&error];
+ BOOL success = [jsonStr writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (!success) {
return error;
}