|
14 | 14 | import android.os.Message; |
15 | 15 | import com.retroarch.browser.preferences.util.ConfigFile; |
16 | 16 | import com.retroarch.browser.preferences.util.UserPreferences; |
| 17 | +import java.io.File; |
| 18 | +import java.io.FileInputStream; |
| 19 | +import java.io.FileOutputStream; |
| 20 | +import java.io.IOException; |
| 21 | +import java.io.InputStream; |
| 22 | +import java.io.OutputStream; |
17 | 23 | import java.lang.reflect.InvocationTargetException; |
18 | 24 | import java.lang.reflect.Method; |
19 | 25 |
|
@@ -58,14 +64,79 @@ public void handleMessage(Message msg) { |
58 | 64 | @Override |
59 | 65 | public void onCreate(Bundle savedInstanceState) { |
60 | 66 | super.onCreate(savedInstanceState); |
61 | | - |
| 67 | + |
62 | 68 | isRunning = true; |
63 | 69 | mDecorView = getWindow().getDecorView(); |
64 | 70 |
|
| 71 | + // Copy external core .so to internal cores directory if needed |
| 72 | + copyExternalCoreIfNeeded(); |
| 73 | + |
65 | 74 | // If QUITFOCUS parameter is provided then enable that Retroarch quits when focus is lost |
66 | 75 | quitfocus = getIntent().hasExtra("QUITFOCUS"); |
67 | 76 | } |
68 | 77 |
|
| 78 | + private void copyExternalCoreIfNeeded() { |
| 79 | + String libretroPath = getIntent().getStringExtra("LIBRETRO"); |
| 80 | + if (libretroPath == null || !libretroPath.endsWith(".so")) |
| 81 | + return; |
| 82 | + |
| 83 | + String dataDir = getApplicationInfo().dataDir; |
| 84 | + |
| 85 | + // Normalize /data/data/ symlink to real dataDir path (/data/user/0/...) |
| 86 | + String datadataPrefix = "/data/data/" + getPackageName(); |
| 87 | + if (libretroPath.startsWith(datadataPrefix)) { |
| 88 | + libretroPath = dataDir + libretroPath.substring(datadataPrefix.length()); |
| 89 | + getIntent().putExtra("LIBRETRO", libretroPath); |
| 90 | + return; |
| 91 | + } |
| 92 | + |
| 93 | + // Already using the real dataDir path |
| 94 | + if (libretroPath.startsWith(dataDir)) |
| 95 | + return; |
| 96 | + |
| 97 | + // External core — copy to internal cores directory |
| 98 | + File srcFile = new File(libretroPath); |
| 99 | + if (!srcFile.isFile()) |
| 100 | + return; |
| 101 | + |
| 102 | + File coresDir = new File(dataDir, "cores"); |
| 103 | + if (!coresDir.exists()) |
| 104 | + coresDir.mkdirs(); |
| 105 | + |
| 106 | + File destFile = new File(coresDir, srcFile.getName()); |
| 107 | + |
| 108 | + // Avoid self-copy if source and destination resolve to the same file |
| 109 | + try { |
| 110 | + if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) { |
| 111 | + getIntent().putExtra("LIBRETRO", destFile.getAbsolutePath()); |
| 112 | + return; |
| 113 | + } |
| 114 | + } catch (IOException e) { |
| 115 | + // If we can't resolve, proceed with copy |
| 116 | + } |
| 117 | + |
| 118 | + try { |
| 119 | + InputStream in = new FileInputStream(srcFile); |
| 120 | + try { |
| 121 | + OutputStream out = new FileOutputStream(destFile); |
| 122 | + try { |
| 123 | + byte[] buf = new byte[8192]; |
| 124 | + int len; |
| 125 | + while ((len = in.read(buf)) > 0) |
| 126 | + out.write(buf, 0, len); |
| 127 | + } finally { |
| 128 | + out.close(); |
| 129 | + } |
| 130 | + } finally { |
| 131 | + in.close(); |
| 132 | + } |
| 133 | + getIntent().putExtra("LIBRETRO", destFile.getAbsolutePath()); |
| 134 | + Log.i("RetroActivityFuture", "Copied external core to: " + destFile.getAbsolutePath()); |
| 135 | + } catch (IOException e) { |
| 136 | + Log.e("RetroActivityFuture", "Failed to copy external core: " + e.getMessage()); |
| 137 | + } |
| 138 | + } |
| 139 | + |
69 | 140 | @Override |
70 | 141 | public void onNewIntent(Intent intent) { |
71 | 142 | super.onNewIntent(intent); |
|
0 commit comments