summaryrefslogtreecommitdiff
path: root/Source/Android/app/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Android/app/src/main/java')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java601
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.kt603
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/AlertMessage.kt1
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.kt24
4 files changed, 617 insertions, 612 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java
deleted file mode 100644
index 7d4714d758..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * Copyright 2013 Dolphin Emulator Project
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-package org.dolphinemu.dolphinemu;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.util.DisplayMetrics;
-import android.view.Surface;
-import android.widget.Toast;
-
-import androidx.annotation.Keep;
-import androidx.core.util.Pair;
-import androidx.fragment.app.FragmentManager;
-
-import org.dolphinemu.dolphinemu.activities.EmulationActivity;
-import org.dolphinemu.dolphinemu.dialogs.AlertMessage;
-import org.dolphinemu.dolphinemu.utils.CompressCallback;
-import org.dolphinemu.dolphinemu.utils.Log;
-
-import java.lang.ref.WeakReference;
-import java.util.concurrent.Semaphore;
-
-/**
- * Class which contains methods that interact
- * with the native side of the Dolphin code.
- */
-public final class NativeLibrary
-{
- private static final Semaphore sAlertMessageSemaphore = new Semaphore(0);
- private static boolean sIsShowingAlertMessage = false;
-
- private static WeakReference<EmulationActivity> sEmulationActivity = new WeakReference<>(null);
-
- /**
- * Returns the current instance of EmulationActivity.
- * There should only ever be one EmulationActivity instantiated.
- */
- public static EmulationActivity getEmulationActivity()
- {
- return sEmulationActivity.get();
- }
-
- /**
- * Button type, for legacy use only
- */
- public static final class ButtonType
- {
- public static final int BUTTON_A = 0;
- public static final int BUTTON_B = 1;
- public static final int BUTTON_START = 2;
- public static final int BUTTON_X = 3;
- public static final int BUTTON_Y = 4;
- public static final int BUTTON_Z = 5;
- public static final int BUTTON_UP = 6;
- public static final int BUTTON_DOWN = 7;
- public static final int BUTTON_LEFT = 8;
- public static final int BUTTON_RIGHT = 9;
- public static final int STICK_MAIN = 10;
- public static final int STICK_MAIN_UP = 11;
- public static final int STICK_MAIN_DOWN = 12;
- public static final int STICK_MAIN_LEFT = 13;
- public static final int STICK_MAIN_RIGHT = 14;
- public static final int STICK_C = 15;
- public static final int STICK_C_UP = 16;
- public static final int STICK_C_DOWN = 17;
- public static final int STICK_C_LEFT = 18;
- public static final int STICK_C_RIGHT = 19;
- public static final int TRIGGER_L = 20;
- public static final int TRIGGER_R = 21;
- public static final int WIIMOTE_BUTTON_A = 100;
- public static final int WIIMOTE_BUTTON_B = 101;
- public static final int WIIMOTE_BUTTON_MINUS = 102;
- public static final int WIIMOTE_BUTTON_PLUS = 103;
- public static final int WIIMOTE_BUTTON_HOME = 104;
- public static final int WIIMOTE_BUTTON_1 = 105;
- public static final int WIIMOTE_BUTTON_2 = 106;
- public static final int WIIMOTE_UP = 107;
- public static final int WIIMOTE_DOWN = 108;
- public static final int WIIMOTE_LEFT = 109;
- public static final int WIIMOTE_RIGHT = 110;
- public static final int WIIMOTE_IR = 111;
- public static final int WIIMOTE_IR_UP = 112;
- public static final int WIIMOTE_IR_DOWN = 113;
- public static final int WIIMOTE_IR_LEFT = 114;
- public static final int WIIMOTE_IR_RIGHT = 115;
- public static final int WIIMOTE_IR_FORWARD = 116;
- public static final int WIIMOTE_IR_BACKWARD = 117;
- public static final int WIIMOTE_IR_HIDE = 118;
- public static final int WIIMOTE_SWING = 119;
- public static final int WIIMOTE_SWING_UP = 120;
- public static final int WIIMOTE_SWING_DOWN = 121;
- public static final int WIIMOTE_SWING_LEFT = 122;
- public static final int WIIMOTE_SWING_RIGHT = 123;
- public static final int WIIMOTE_SWING_FORWARD = 124;
- public static final int WIIMOTE_SWING_BACKWARD = 125;
- public static final int WIIMOTE_TILT = 126;
- public static final int WIIMOTE_TILT_FORWARD = 127;
- public static final int WIIMOTE_TILT_BACKWARD = 128;
- public static final int WIIMOTE_TILT_LEFT = 129;
- public static final int WIIMOTE_TILT_RIGHT = 130;
- public static final int WIIMOTE_TILT_MODIFIER = 131;
- public static final int WIIMOTE_SHAKE_X = 132;
- public static final int WIIMOTE_SHAKE_Y = 133;
- public static final int WIIMOTE_SHAKE_Z = 134;
- public static final int NUNCHUK_BUTTON_C = 200;
- public static final int NUNCHUK_BUTTON_Z = 201;
- public static final int NUNCHUK_STICK = 202;
- public static final int NUNCHUK_STICK_UP = 203;
- public static final int NUNCHUK_STICK_DOWN = 204;
- public static final int NUNCHUK_STICK_LEFT = 205;
- public static final int NUNCHUK_STICK_RIGHT = 206;
- public static final int NUNCHUK_SWING = 207;
- public static final int NUNCHUK_SWING_UP = 208;
- public static final int NUNCHUK_SWING_DOWN = 209;
- public static final int NUNCHUK_SWING_LEFT = 210;
- public static final int NUNCHUK_SWING_RIGHT = 211;
- public static final int NUNCHUK_SWING_FORWARD = 212;
- public static final int NUNCHUK_SWING_BACKWARD = 213;
- public static final int NUNCHUK_TILT = 214;
- public static final int NUNCHUK_TILT_FORWARD = 215;
- public static final int NUNCHUK_TILT_BACKWARD = 216;
- public static final int NUNCHUK_TILT_LEFT = 217;
- public static final int NUNCHUK_TILT_RIGHT = 218;
- public static final int NUNCHUK_TILT_MODIFIER = 219;
- public static final int NUNCHUK_SHAKE_X = 220;
- public static final int NUNCHUK_SHAKE_Y = 221;
- public static final int NUNCHUK_SHAKE_Z = 222;
- public static final int CLASSIC_BUTTON_A = 300;
- public static final int CLASSIC_BUTTON_B = 301;
- public static final int CLASSIC_BUTTON_X = 302;
- public static final int CLASSIC_BUTTON_Y = 303;
- public static final int CLASSIC_BUTTON_MINUS = 304;
- public static final int CLASSIC_BUTTON_PLUS = 305;
- public static final int CLASSIC_BUTTON_HOME = 306;
- public static final int CLASSIC_BUTTON_ZL = 307;
- public static final int CLASSIC_BUTTON_ZR = 308;
- public static final int CLASSIC_DPAD_UP = 309;
- public static final int CLASSIC_DPAD_DOWN = 310;
- public static final int CLASSIC_DPAD_LEFT = 311;
- public static final int CLASSIC_DPAD_RIGHT = 312;
- public static final int CLASSIC_STICK_LEFT = 313;
- public static final int CLASSIC_STICK_LEFT_UP = 314;
- public static final int CLASSIC_STICK_LEFT_DOWN = 315;
- public static final int CLASSIC_STICK_LEFT_LEFT = 316;
- public static final int CLASSIC_STICK_LEFT_RIGHT = 317;
- public static final int CLASSIC_STICK_RIGHT = 318;
- public static final int CLASSIC_STICK_RIGHT_UP = 319;
- public static final int CLASSIC_STICK_RIGHT_DOWN = 320;
- public static final int CLASSIC_STICK_RIGHT_LEFT = 321;
- public static final int CLASSIC_STICK_RIGHT_RIGHT = 322;
- public static final int CLASSIC_TRIGGER_L = 323;
- public static final int CLASSIC_TRIGGER_R = 324;
- public static final int GUITAR_BUTTON_MINUS = 400;
- public static final int GUITAR_BUTTON_PLUS = 401;
- public static final int GUITAR_FRET_GREEN = 402;
- public static final int GUITAR_FRET_RED = 403;
- public static final int GUITAR_FRET_YELLOW = 404;
- public static final int GUITAR_FRET_BLUE = 405;
- public static final int GUITAR_FRET_ORANGE = 406;
- public static final int GUITAR_STRUM_UP = 407;
- public static final int GUITAR_STRUM_DOWN = 408;
- public static final int GUITAR_STICK = 409;
- public static final int GUITAR_STICK_UP = 410;
- public static final int GUITAR_STICK_DOWN = 411;
- public static final int GUITAR_STICK_LEFT = 412;
- public static final int GUITAR_STICK_RIGHT = 413;
- public static final int GUITAR_WHAMMY_BAR = 414;
- public static final int DRUMS_BUTTON_MINUS = 500;
- public static final int DRUMS_BUTTON_PLUS = 501;
- public static final int DRUMS_PAD_RED = 502;
- public static final int DRUMS_PAD_YELLOW = 503;
- public static final int DRUMS_PAD_BLUE = 504;
- public static final int DRUMS_PAD_GREEN = 505;
- public static final int DRUMS_PAD_ORANGE = 506;
- public static final int DRUMS_PAD_BASS = 507;
- public static final int DRUMS_STICK = 508;
- public static final int DRUMS_STICK_UP = 509;
- public static final int DRUMS_STICK_DOWN = 510;
- public static final int DRUMS_STICK_LEFT = 511;
- public static final int DRUMS_STICK_RIGHT = 512;
- public static final int TURNTABLE_BUTTON_GREEN_LEFT = 600;
- public static final int TURNTABLE_BUTTON_RED_LEFT = 601;
- public static final int TURNTABLE_BUTTON_BLUE_LEFT = 602;
- public static final int TURNTABLE_BUTTON_GREEN_RIGHT = 603;
- public static final int TURNTABLE_BUTTON_RED_RIGHT = 604;
- public static final int TURNTABLE_BUTTON_BLUE_RIGHT = 605;
- public static final int TURNTABLE_BUTTON_MINUS = 606;
- public static final int TURNTABLE_BUTTON_PLUS = 607;
- public static final int TURNTABLE_BUTTON_HOME = 608;
- public static final int TURNTABLE_BUTTON_EUPHORIA = 609;
- public static final int TURNTABLE_TABLE_LEFT = 610;
- public static final int TURNTABLE_TABLE_LEFT_LEFT = 611;
- public static final int TURNTABLE_TABLE_LEFT_RIGHT = 612;
- public static final int TURNTABLE_TABLE_RIGHT = 613;
- public static final int TURNTABLE_TABLE_RIGHT_LEFT = 614;
- public static final int TURNTABLE_TABLE_RIGHT_RIGHT = 615;
- public static final int TURNTABLE_STICK = 616;
- public static final int TURNTABLE_STICK_UP = 617;
- public static final int TURNTABLE_STICK_DOWN = 618;
- public static final int TURNTABLE_STICK_LEFT = 619;
- public static final int TURNTABLE_STICK_RIGHT = 620;
- public static final int TURNTABLE_EFFECT_DIAL = 621;
- public static final int TURNTABLE_CROSSFADE = 622;
- public static final int TURNTABLE_CROSSFADE_LEFT = 623;
- public static final int TURNTABLE_CROSSFADE_RIGHT = 624;
- public static final int WIIMOTE_ACCEL_LEFT = 625;
- public static final int WIIMOTE_ACCEL_RIGHT = 626;
- public static final int WIIMOTE_ACCEL_FORWARD = 627;
- public static final int WIIMOTE_ACCEL_BACKWARD = 628;
- public static final int WIIMOTE_ACCEL_UP = 629;
- public static final int WIIMOTE_ACCEL_DOWN = 630;
- public static final int WIIMOTE_GYRO_PITCH_UP = 631;
- public static final int WIIMOTE_GYRO_PITCH_DOWN = 632;
- public static final int WIIMOTE_GYRO_ROLL_LEFT = 633;
- public static final int WIIMOTE_GYRO_ROLL_RIGHT = 634;
- public static final int WIIMOTE_GYRO_YAW_LEFT = 635;
- public static final int WIIMOTE_GYRO_YAW_RIGHT = 636;
- }
-
- /**
- * Button states
- */
- public static final class ButtonState
- {
- public static final int RELEASED = 0;
- public static final int PRESSED = 1;
- }
-
- private NativeLibrary()
- {
- // Disallows instantiation.
- }
-
- /**
- * Gets the Dolphin version string.
- *
- * @return the Dolphin version string.
- */
- public static native String GetVersionString();
-
- public static native String GetGitRevision();
-
- /**
- * Saves a screen capture of the game
- */
- public static native void SaveScreenShot();
-
- /**
- * Saves a game state to the slot number.
- *
- * @param slot The slot location to save state to.
- * @param wait If false, returns as early as possible.
- * If true, returns once the savestate has been written to disk.
- */
- public static native void SaveState(int slot, boolean wait);
-
- /**
- * Saves a game state to the specified path.
- *
- * @param path The path to save state to.
- * @param wait If false, returns as early as possible.
- * If true, returns once the savestate has been written to disk.
- */
- public static native void SaveStateAs(String path, boolean wait);
-
- /**
- * Loads a game state from the slot number.
- *
- * @param slot The slot location to load state from.
- */
- public static native void LoadState(int slot);
-
- /**
- * Loads a game state from the specified path.
- *
- * @param path The path to load state from.
- */
- public static native void LoadStateAs(String path);
-
- /**
- * Returns when the savestate in the given slot was created, or 0 if the slot is empty.
- */
- public static native long GetUnixTimeOfStateSlot(int slot);
-
- /**
- * Sets the current working user directory
- * If not set, it auto-detects a location
- */
- public static native void SetUserDirectory(String directory);
-
- /**
- * Returns the current working user directory
- */
- public static native String GetUserDirectory();
-
- public static native void SetCacheDirectory(String directory);
-
- public static native String GetCacheDirectory();
-
- public static native int DefaultCPUCore();
-
- public static native String GetDefaultGraphicsBackendConfigName();
-
- public static native int GetMaxLogLevel();
-
- public static native void ReloadConfig();
-
- public static native void ResetDolphinSettings();
-
- public static native void UpdateGCAdapterScanThread();
-
- /**
- * Initializes the native parts of the app.
- *
- * Should be called at app start before running any other native code
- * (other than the native methods in DirectoryInitialization).
- */
- public static native void Initialize();
-
- /**
- * Tells analytics that Dolphin has been started.
- *
- * Since users typically don't explicitly close Android apps, it's appropriate to
- * call this not only when the app starts but also when the user returns to the app
- * after not using it for a significant amount of time.
- */
- public static native void ReportStartToAnalytics();
-
- public static native void GenerateNewStatisticsId();
-
- /**
- * Begins emulation.
- */
- public static native void Run(String[] path, boolean riivolution);
-
- /**
- * Begins emulation from the specified savestate.
- */
- public static native void Run(String[] path, boolean riivolution, String savestatePath,
- boolean deleteSavestate);
-
- /**
- * Begins emulation of the System Menu.
- */
- public static native void RunSystemMenu();
-
- public static native void ChangeDisc(String path);
-
- // Surface Handling
- public static native void SurfaceChanged(Surface surf);
-
- public static native void SurfaceDestroyed();
-
- public static native boolean HasSurface();
-
- /**
- * Unpauses emulation from a paused state.
- */
- public static native void UnPauseEmulation();
-
- /**
- * Pauses emulation.
- */
- public static native void PauseEmulation(boolean overrideAchievementRestrictions);
-
- /**
- * Stops emulation.
- */
- public static native void StopEmulation();
-
- /**
- * Ensures that IsRunning will return true from now on until emulation exits.
- * (If this is not called, IsRunning will start returning true at some point
- * after calling Run.)
- */
- public static native void SetIsBooting();
-
- /**
- * Returns true if emulation is running (or is paused).
- */
- public static native boolean IsRunning();
-
- /**
- * Returns true if emulation is running and not paused.
- */
- public static native boolean IsRunningAndUnpaused();
-
- /**
- * Returns true if emulation is fully shut down.
- */
- public static native boolean IsUninitialized();
-
- /**
- * Re-initialize software JitBlock profiling data
- */
- public static native void WipeJitBlockProfilingData();
-
- /**
- * Writes out the JitBlock Cache log dump
- */
- public static native void WriteJitBlockLogDump();
-
- /**
- * Native EGL functions not exposed by Java bindings
- **/
- public static native void eglBindAPI(int api);
-
- /**
- * Provides a way to refresh the connections on Wiimotes
- */
- public static native void RefreshWiimotes();
-
- public static native Pair<String, String>[] GetLogTypeNames();
-
- public static native void ReloadLoggerConfig();
-
- public static native boolean ConvertDiscImage(String inPath, String outPath, int platform,
- int format, int blockSize, int compression, int compressionLevel, boolean scrub,
- CompressCallback callback);
-
- public static native String FormatSize(long bytes, int decimals);
-
- public static native void SetObscuredPixelsLeft(int width);
-
- public static native void SetObscuredPixelsTop(int height);
-
- public static native boolean IsGameMetadataValid();
-
- public static boolean IsEmulatingWii()
- {
- CheckGameMetadataValid();
- return IsEmulatingWiiUnchecked();
- }
-
- public static String GetCurrentGameID()
- {
- CheckGameMetadataValid();
- return GetCurrentGameIDUnchecked();
- }
-
- public static String GetCurrentTitleDescription()
- {
- CheckGameMetadataValid();
- return GetCurrentTitleDescriptionUnchecked();
- }
-
- private static void CheckGameMetadataValid()
- {
- if (!IsGameMetadataValid())
- {
- throw new IllegalStateException("No game is running");
- }
- }
-
- private static native boolean IsEmulatingWiiUnchecked();
-
- private static native String GetCurrentGameIDUnchecked();
-
- private static native String GetCurrentTitleDescriptionUnchecked();
-
- @Keep
- public static void displayToastMsg(final String text, final boolean long_length)
- {
- final int length = long_length ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT;
- new Handler(Looper.getMainLooper())
- .post(() -> Toast.makeText(DolphinApplication.getAppContext(), text, length).show());
- }
-
- @Keep
- public static boolean displayAlertMsg(final String caption, final String text,
- final boolean yesNo, final boolean isWarning, final boolean nonBlocking)
- {
- Log.error("[NativeLibrary] Alert: " + text);
- final EmulationActivity emulationActivity = sEmulationActivity.get();
- boolean result = false;
-
- // We can't use AlertMessages unless we have a non-null activity reference
- // and are allowed to block. As a fallback, we can use toasts.
- if (emulationActivity == null || nonBlocking)
- {
- displayToastMsg(text, true);
- }
- else
- {
- sIsShowingAlertMessage = true;
-
- emulationActivity.runOnUiThread(() ->
- {
- FragmentManager fragmentManager = emulationActivity.getSupportFragmentManager();
- if (fragmentManager.isStateSaved())
- {
- // The activity is being destroyed, so we can't use it to display an AlertMessage.
- // Fall back to a toast.
- Toast.makeText(emulationActivity, text, Toast.LENGTH_LONG).show();
- NotifyAlertMessageLock();
- }
- else
- {
- AlertMessage.Companion.newInstance(caption, text, yesNo, isWarning)
- .show(fragmentManager, "AlertMessage");
- }
- });
-
- // Wait for the lock to notify that it is complete.
- try
- {
- sAlertMessageSemaphore.acquire();
- }
- catch (InterruptedException ignored)
- {
- }
-
- if (yesNo)
- {
- result = AlertMessage.Companion.getAlertResult();
- }
- }
-
- sIsShowingAlertMessage = false;
- return result;
- }
-
- public static boolean IsShowingAlertMessage()
- {
- return sIsShowingAlertMessage;
- }
-
- public static void NotifyAlertMessageLock()
- {
- sAlertMessageSemaphore.release();
- }
-
- public static void setEmulationActivity(EmulationActivity emulationActivity)
- {
- Log.verbose("[NativeLibrary] Registering EmulationActivity.");
- sEmulationActivity = new WeakReference<>(emulationActivity);
- }
-
- public static void clearEmulationActivity()
- {
- Log.verbose("[NativeLibrary] Unregistering EmulationActivity.");
-
- sEmulationActivity.clear();
- }
-
- @Keep
- public static void finishEmulationActivity()
- {
- final EmulationActivity emulationActivity = sEmulationActivity.get();
- if (emulationActivity == null)
- {
- Log.warning("[NativeLibrary] EmulationActivity is null.");
- }
- else
- {
- Log.verbose("[NativeLibrary] Finishing EmulationActivity.");
- emulationActivity.runOnUiThread(emulationActivity::finish);
- }
- }
-
- @Keep
- public static void updateTouchPointer()
- {
- final EmulationActivity emulationActivity = sEmulationActivity.get();
- if (emulationActivity == null)
- {
- Log.warning("[NativeLibrary] EmulationActivity is null.");
- }
- else
- {
- emulationActivity.runOnUiThread(emulationActivity::initInputPointer);
- }
- }
-
- @Keep
- public static void onTitleChanged()
- {
- final EmulationActivity emulationActivity = sEmulationActivity.get();
- if (emulationActivity == null)
- {
- Log.warning("[NativeLibrary] EmulationActivity is null.");
- }
- else
- {
- emulationActivity.runOnUiThread(emulationActivity::onTitleChanged);
- }
- }
-
- @Keep
- public static float getRenderSurfaceScale()
- {
- DisplayMetrics metrics = new DisplayMetrics();
- sEmulationActivity.get().getWindowManager().getDefaultDisplay().getMetrics(metrics);
- return metrics.scaledDensity;
- }
-
- public static native float GetGameAspectRatio();
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.kt
new file mode 100644
index 0000000000..0b6490b290
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.kt
@@ -0,0 +1,603 @@
+/*
+ * Copyright 2013 Dolphin Emulator Project
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+package org.dolphinemu.dolphinemu
+
+import android.content.res.Resources
+import android.view.Surface
+import android.widget.Toast
+import androidx.annotation.Keep
+import androidx.core.content.ContextCompat
+import androidx.core.util.Pair
+import org.dolphinemu.dolphinemu.activities.EmulationActivity
+import org.dolphinemu.dolphinemu.dialogs.AlertMessage
+import org.dolphinemu.dolphinemu.utils.CompressCallback
+import org.dolphinemu.dolphinemu.utils.Log
+import java.lang.ref.WeakReference
+import java.util.concurrent.Semaphore
+
+/**
+ * Class which contains methods that interact
+ * with the native side of the Dolphin code.
+ */
+object NativeLibrary {
+ /**
+ * Button type, for legacy use only.
+ */
+ object ButtonType {
+ const val BUTTON_A = 0
+ const val BUTTON_B = 1
+ const val BUTTON_START = 2
+ const val BUTTON_X = 3
+ const val BUTTON_Y = 4
+ const val BUTTON_Z = 5
+ const val BUTTON_UP = 6
+ const val BUTTON_DOWN = 7
+ const val BUTTON_LEFT = 8
+ const val BUTTON_RIGHT = 9
+ const val STICK_MAIN = 10
+ const val STICK_MAIN_UP = 11
+ const val STICK_MAIN_DOWN = 12
+ const val STICK_MAIN_LEFT = 13
+ const val STICK_MAIN_RIGHT = 14
+ const val STICK_C = 15
+ const val STICK_C_UP = 16
+ const val STICK_C_DOWN = 17
+ const val STICK_C_LEFT = 18
+ const val STICK_C_RIGHT = 19
+ const val TRIGGER_L = 20
+ const val TRIGGER_R = 21
+ const val WIIMOTE_BUTTON_A = 100
+ const val WIIMOTE_BUTTON_B = 101
+ const val WIIMOTE_BUTTON_MINUS = 102
+ const val WIIMOTE_BUTTON_PLUS = 103
+ const val WIIMOTE_BUTTON_HOME = 104
+ const val WIIMOTE_BUTTON_1 = 105
+ const val WIIMOTE_BUTTON_2 = 106
+ const val WIIMOTE_UP = 107
+ const val WIIMOTE_DOWN = 108
+ const val WIIMOTE_LEFT = 109
+ const val WIIMOTE_RIGHT = 110
+ const val WIIMOTE_IR = 111
+ const val WIIMOTE_IR_UP = 112
+ const val WIIMOTE_IR_DOWN = 113
+ const val WIIMOTE_IR_LEFT = 114
+ const val WIIMOTE_IR_RIGHT = 115
+ const val WIIMOTE_IR_FORWARD = 116
+ const val WIIMOTE_IR_BACKWARD = 117
+ const val WIIMOTE_IR_HIDE = 118
+ const val WIIMOTE_SWING = 119
+ const val WIIMOTE_SWING_UP = 120
+ const val WIIMOTE_SWING_DOWN = 121
+ const val WIIMOTE_SWING_LEFT = 122
+ const val WIIMOTE_SWING_RIGHT = 123
+ const val WIIMOTE_SWING_FORWARD = 124
+ const val WIIMOTE_SWING_BACKWARD = 125
+ const val WIIMOTE_TILT = 126
+ const val WIIMOTE_TILT_FORWARD = 127
+ const val WIIMOTE_TILT_BACKWARD = 128
+ const val WIIMOTE_TILT_LEFT = 129
+ const val WIIMOTE_TILT_RIGHT = 130
+ const val WIIMOTE_TILT_MODIFIER = 131
+ const val WIIMOTE_SHAKE_X = 132
+ const val WIIMOTE_SHAKE_Y = 133
+ const val WIIMOTE_SHAKE_Z = 134
+ const val NUNCHUK_BUTTON_C = 200
+ const val NUNCHUK_BUTTON_Z = 201
+ const val NUNCHUK_STICK = 202
+ const val NUNCHUK_STICK_UP = 203
+ const val NUNCHUK_STICK_DOWN = 204
+ const val NUNCHUK_STICK_LEFT = 205
+ const val NUNCHUK_STICK_RIGHT = 206
+ const val NUNCHUK_SWING = 207
+ const val NUNCHUK_SWING_UP = 208
+ const val NUNCHUK_SWING_DOWN = 209
+ const val NUNCHUK_SWING_LEFT = 210
+ const val NUNCHUK_SWING_RIGHT = 211
+ const val NUNCHUK_SWING_FORWARD = 212
+ const val NUNCHUK_SWING_BACKWARD = 213
+ const val NUNCHUK_TILT = 214
+ const val NUNCHUK_TILT_FORWARD = 215
+ const val NUNCHUK_TILT_BACKWARD = 216
+ const val NUNCHUK_TILT_LEFT = 217
+ const val NUNCHUK_TILT_RIGHT = 218
+ const val NUNCHUK_TILT_MODIFIER = 219
+ const val NUNCHUK_SHAKE_X = 220
+ const val NUNCHUK_SHAKE_Y = 221
+ const val NUNCHUK_SHAKE_Z = 222
+ const val CLASSIC_BUTTON_A = 300
+ const val CLASSIC_BUTTON_B = 301
+ const val CLASSIC_BUTTON_X = 302
+ const val CLASSIC_BUTTON_Y = 303
+ const val CLASSIC_BUTTON_MINUS = 304
+ const val CLASSIC_BUTTON_PLUS = 305
+ const val CLASSIC_BUTTON_HOME = 306
+ const val CLASSIC_BUTTON_ZL = 307
+ const val CLASSIC_BUTTON_ZR = 308
+ const val CLASSIC_DPAD_UP = 309
+ const val CLASSIC_DPAD_DOWN = 310
+ const val CLASSIC_DPAD_LEFT = 311
+ const val CLASSIC_DPAD_RIGHT = 312
+ const val CLASSIC_STICK_LEFT = 313
+ const val CLASSIC_STICK_LEFT_UP = 314
+ const val CLASSIC_STICK_LEFT_DOWN = 315
+ const val CLASSIC_STICK_LEFT_LEFT = 316
+ const val CLASSIC_STICK_LEFT_RIGHT = 317
+ const val CLASSIC_STICK_RIGHT = 318
+ const val CLASSIC_STICK_RIGHT_UP = 319
+ const val CLASSIC_STICK_RIGHT_DOWN = 320
+ const val CLASSIC_STICK_RIGHT_LEFT = 321
+ const val CLASSIC_STICK_RIGHT_RIGHT = 322
+ const val CLASSIC_TRIGGER_L = 323
+ const val CLASSIC_TRIGGER_R = 324
+ const val GUITAR_BUTTON_MINUS = 400
+ const val GUITAR_BUTTON_PLUS = 401
+ const val GUITAR_FRET_GREEN = 402
+ const val GUITAR_FRET_RED = 403
+ const val GUITAR_FRET_YELLOW = 404
+ const val GUITAR_FRET_BLUE = 405
+ const val GUITAR_FRET_ORANGE = 406
+ const val GUITAR_STRUM_UP = 407
+ const val GUITAR_STRUM_DOWN = 408
+ const val GUITAR_STICK = 409
+ const val GUITAR_STICK_UP = 410
+ const val GUITAR_STICK_DOWN = 411
+ const val GUITAR_STICK_LEFT = 412
+ const val GUITAR_STICK_RIGHT = 413
+ const val GUITAR_WHAMMY_BAR = 414
+ const val DRUMS_BUTTON_MINUS = 500
+ const val DRUMS_BUTTON_PLUS = 501
+ const val DRUMS_PAD_RED = 502
+ const val DRUMS_PAD_YELLOW = 503
+ const val DRUMS_PAD_BLUE = 504
+ const val DRUMS_PAD_GREEN = 505
+ const val DRUMS_PAD_ORANGE = 506
+ const val DRUMS_PAD_BASS = 507
+ const val DRUMS_STICK = 508
+ const val DRUMS_STICK_UP = 509
+ const val DRUMS_STICK_DOWN = 510
+ const val DRUMS_STICK_LEFT = 511
+ const val DRUMS_STICK_RIGHT = 512
+ const val TURNTABLE_BUTTON_GREEN_LEFT = 600
+ const val TURNTABLE_BUTTON_RED_LEFT = 601
+ const val TURNTABLE_BUTTON_BLUE_LEFT = 602
+ const val TURNTABLE_BUTTON_GREEN_RIGHT = 603
+ const val TURNTABLE_BUTTON_RED_RIGHT = 604
+ const val TURNTABLE_BUTTON_BLUE_RIGHT = 605
+ const val TURNTABLE_BUTTON_MINUS = 606
+ const val TURNTABLE_BUTTON_PLUS = 607
+ const val TURNTABLE_BUTTON_HOME = 608
+ const val TURNTABLE_BUTTON_EUPHORIA = 609
+ const val TURNTABLE_TABLE_LEFT = 610
+ const val TURNTABLE_TABLE_LEFT_LEFT = 611
+ const val TURNTABLE_TABLE_LEFT_RIGHT = 612
+ const val TURNTABLE_TABLE_RIGHT = 613
+ const val TURNTABLE_TABLE_RIGHT_LEFT = 614
+ const val TURNTABLE_TABLE_RIGHT_RIGHT = 615
+ const val TURNTABLE_STICK = 616
+ const val TURNTABLE_STICK_UP = 617
+ const val TURNTABLE_STICK_DOWN = 618
+ const val TURNTABLE_STICK_LEFT = 619
+ const val TURNTABLE_STICK_RIGHT = 620
+ const val TURNTABLE_EFFECT_DIAL = 621
+ const val TURNTABLE_CROSSFADE = 622
+ const val TURNTABLE_CROSSFADE_LEFT = 623
+ const val TURNTABLE_CROSSFADE_RIGHT = 624
+ const val WIIMOTE_ACCEL_LEFT = 625
+ const val WIIMOTE_ACCEL_RIGHT = 626
+ const val WIIMOTE_ACCEL_FORWARD = 627
+ const val WIIMOTE_ACCEL_BACKWARD = 628
+ const val WIIMOTE_ACCEL_UP = 629
+ const val WIIMOTE_ACCEL_DOWN = 630
+ const val WIIMOTE_GYRO_PITCH_UP = 631
+ const val WIIMOTE_GYRO_PITCH_DOWN = 632
+ const val WIIMOTE_GYRO_ROLL_LEFT = 633
+ const val WIIMOTE_GYRO_ROLL_RIGHT = 634
+ const val WIIMOTE_GYRO_YAW_LEFT = 635
+ const val WIIMOTE_GYRO_YAW_RIGHT = 636
+ }
+
+ object ButtonState {
+ const val RELEASED = 0
+ const val PRESSED = 1
+ }
+
+ private val alertMessageSemaphore = Semaphore(0)
+
+ @Volatile
+ private var isShowingAlertMessage = false
+ private var emulationActivityRef = WeakReference<EmulationActivity?>(null)
+
+ /**
+ * Returns the current instance of EmulationActivity.
+ * There should only ever be one EmulationActivity instantiated.
+ */
+ @JvmStatic
+ fun getEmulationActivity(): EmulationActivity? = emulationActivityRef.get()
+
+ @JvmStatic
+ external fun GetVersionString(): String
+
+ @JvmStatic
+ external fun GetGitRevision(): String
+
+ /**
+ * Saves a screen capture of the game.
+ */
+ @JvmStatic
+ external fun SaveScreenShot()
+
+ /**
+ * Saves a game state to the slot number.
+ *
+ * @param slot The slot location to save state to.
+ * @param wait If false, returns as early as possible. If true, returns once the savestate has been written to disk.
+ */
+ @JvmStatic
+ external fun SaveState(slot: Int, wait: Boolean)
+
+ /**
+ * Saves a game state to the specified path.
+ *
+ * @param path The path to save state to.
+ * @param wait If false, returns as early as possible. If true, returns once the savestate has been written to disk.
+ */
+ @JvmStatic
+ external fun SaveStateAs(path: String, wait: Boolean)
+
+ /**
+ * Loads a game state from the slot number.
+ *
+ * @param slot The slot location to load state from.
+ */
+ @JvmStatic
+ external fun LoadState(slot: Int)
+
+ /**
+ * Loads a game state from the specified path.
+ *
+ * @param path The path to load state from.
+ */
+ @JvmStatic
+ external fun LoadStateAs(path: String)
+
+ /**
+ * Returns when the savestate in the given slot was created, or 0 if the slot is empty.
+ */
+ @JvmStatic
+ external fun GetUnixTimeOfStateSlot(slot: Int): Long
+
+ /**
+ * Sets the current working user directory. If not set, it auto-detects a location.
+ */
+ @JvmStatic
+ external fun SetUserDirectory(directory: String)
+
+ /**
+ * Returns the current working user directory.
+ */
+ @JvmStatic
+ external fun GetUserDirectory(): String
+
+ @JvmStatic
+ external fun SetCacheDirectory(directory: String)
+
+ @JvmStatic
+ external fun GetCacheDirectory(): String
+
+ @JvmStatic
+ external fun DefaultCPUCore(): Int
+
+ @JvmStatic
+ external fun GetDefaultGraphicsBackendConfigName(): String
+
+ @JvmStatic
+ external fun GetMaxLogLevel(): Int
+
+ @JvmStatic
+ external fun ReloadConfig()
+
+ @JvmStatic
+ external fun ResetDolphinSettings()
+
+ @JvmStatic
+ external fun UpdateGCAdapterScanThread()
+
+ /**
+ * Initializes the native parts of the app.
+ *
+ * Should be called at app start before running any other native code
+ * (other than the native methods in DirectoryInitialization).
+ */
+ @JvmStatic
+ external fun Initialize()
+
+ /**
+ * Tells analytics that Dolphin has been started.
+ *
+ * Since users typically don't explicitly close Android apps, it's appropriate to
+ * call this not only when the app starts but also when the user returns to the app
+ * after not using it for a significant amount of time.
+ */
+ @JvmStatic
+ external fun ReportStartToAnalytics()
+
+ @JvmStatic
+ external fun GenerateNewStatisticsId()
+
+ /**
+ * Begins emulation.
+ */
+ @JvmStatic
+ external fun Run(path: Array<String>, riivolution: Boolean)
+
+ /**
+ * Begins emulation from the specified savestate.
+ */
+ @JvmStatic
+ external fun Run(
+ path: Array<String>, riivolution: Boolean, savestatePath: String, deleteSavestate: Boolean
+ )
+
+ /**
+ * Begins emulation of the System Menu.
+ */
+ @JvmStatic
+ external fun RunSystemMenu()
+
+ @JvmStatic
+ external fun ChangeDisc(path: String)
+
+ @JvmStatic
+ external fun SurfaceChanged(surf: Surface)
+
+ @JvmStatic
+ external fun SurfaceDestroyed()
+
+ @JvmStatic
+ external fun HasSurface(): Boolean
+
+ @JvmStatic
+ external fun UnPauseEmulation()
+
+ @JvmStatic
+ external fun PauseEmulation(overrideAchievementRestrictions: Boolean)
+
+ @JvmStatic
+ external fun StopEmulation()
+
+ /**
+ * Ensures that IsRunning will return true from now on until emulation exits.
+ * (If this is not called, IsRunning will start returning true at some point
+ * after calling Run.)
+ */
+ @JvmStatic
+ external fun SetIsBooting()
+
+ /**
+ * Returns true if emulation is running or paused.
+ */
+ @JvmStatic
+ external fun IsRunning(): Boolean
+
+ /**
+ * Returns true if emulation is running and not paused.
+ */
+ @JvmStatic
+ external fun IsRunningAndUnpaused(): Boolean
+
+ /**
+ * Returns true if emulation is fully shut down.
+ */
+ @JvmStatic
+ external fun IsUninitialized(): Boolean
+
+ /**
+ * Re-initializes software JitBlock profiling data.
+ */
+ @JvmStatic
+ external fun WipeJitBlockProfilingData()
+
+ /**
+ * Writes out the JitBlock Cache log dump.
+ */
+ @JvmStatic
+ external fun WriteJitBlockLogDump()
+
+ /**
+ * Native EGL functions not exposed by Java bindings.
+ */
+ @JvmStatic
+ external fun eglBindAPI(api: Int)
+
+ /**
+ * Provides a way to refresh Wiimote connections.
+ */
+ @JvmStatic
+ external fun RefreshWiimotes()
+
+ @JvmStatic
+ external fun GetLogTypeNames(): Array<Pair<String, String>>
+
+ @JvmStatic
+ external fun ReloadLoggerConfig()
+
+ @JvmStatic
+ external fun ConvertDiscImage(
+ inPath: String,
+ outPath: String,
+ platform: Int,
+ format: Int,
+ blockSize: Int,
+ compression: Int,
+ compressionLevel: Int,
+ scrub: Boolean,
+ callback: CompressCallback
+ ): Boolean
+
+ @JvmStatic
+ external fun FormatSize(bytes: Long, decimals: Int): String
+
+ @JvmStatic
+ external fun SetObscuredPixelsLeft(width: Int)
+
+ @JvmStatic
+ external fun SetObscuredPixelsTop(height: Int)
+
+ @JvmStatic
+ external fun IsGameMetadataValid(): Boolean
+
+ @JvmStatic
+ external fun GetGameAspectRatio(): Float
+
+ @JvmStatic
+ fun IsEmulatingWii(): Boolean {
+ checkGameMetadataValid()
+ return IsEmulatingWiiUnchecked()
+ }
+
+ @JvmStatic
+ fun GetCurrentGameID(): String {
+ checkGameMetadataValid()
+ return GetCurrentGameIDUnchecked()
+ }
+
+ @JvmStatic
+ fun GetCurrentTitleDescription(): String {
+ checkGameMetadataValid()
+ return GetCurrentTitleDescriptionUnchecked()
+ }
+
+ @JvmStatic
+ @Keep
+ fun displayToastMsg(text: String, long_length: Boolean) {
+ val context = DolphinApplication.getAppContext()
+ val length = if (long_length) Toast.LENGTH_LONG else Toast.LENGTH_SHORT
+ ContextCompat.getMainExecutor(context).execute {
+ Toast.makeText(context, text, length).show()
+ }
+ }
+
+ @JvmStatic
+ @Keep
+ fun displayAlertMsg(
+ caption: String, text: String, yesNo: Boolean, isWarning: Boolean, nonBlocking: Boolean
+ ): Boolean {
+ Log.error("[NativeLibrary] Alert: $text")
+ val emulationActivity = emulationActivityRef.get()
+ var result = false
+
+ // We can't use AlertMessages unless we have a non-null activity reference
+ // and are allowed to block. As a fallback, we can use toasts.
+ if (emulationActivity == null || nonBlocking) {
+ displayToastMsg(text, true)
+ } else {
+ isShowingAlertMessage = true
+
+ emulationActivity.runOnUiThread {
+ val fragmentManager = emulationActivity.supportFragmentManager
+ if (fragmentManager.isStateSaved) {
+ // The activity is being destroyed, so we can't use it to display an AlertMessage.
+ // Fall back to a toast.
+ Toast.makeText(emulationActivity, text, Toast.LENGTH_LONG).show()
+ NotifyAlertMessageLock()
+ } else {
+ AlertMessage.newInstance(caption, text, yesNo, isWarning)
+ .show(fragmentManager, "AlertMessage")
+ }
+ }
+
+ // Wait for the lock to notify that it is complete.
+ try {
+ alertMessageSemaphore.acquire()
+ } catch (ignored: InterruptedException) {
+ Thread.currentThread().interrupt()
+ }
+
+ if (yesNo) {
+ result = AlertMessage.getAlertResult()
+ }
+ }
+
+ isShowingAlertMessage = false
+ return result
+ }
+
+ @JvmStatic
+ fun IsShowingAlertMessage(): Boolean = isShowingAlertMessage
+
+ @JvmStatic
+ fun NotifyAlertMessageLock() {
+ alertMessageSemaphore.release()
+ }
+
+ @JvmStatic
+ fun setEmulationActivity(emulationActivity: EmulationActivity) {
+ Log.verbose("[NativeLibrary] Registering EmulationActivity.")
+ emulationActivityRef = WeakReference(emulationActivity)
+ }
+
+ @JvmStatic
+ fun clearEmulationActivity() {
+ Log.verbose("[NativeLibrary] Unregistering EmulationActivity.")
+ emulationActivityRef.clear()
+ }
+
+ @JvmStatic
+ @Keep
+ fun finishEmulationActivity() {
+ val emulationActivity = emulationActivityRef.get()
+ if (emulationActivity == null) {
+ Log.warning("[NativeLibrary] EmulationActivity is null.")
+ } else {
+ Log.verbose("[NativeLibrary] Finishing EmulationActivity.")
+ emulationActivity.runOnUiThread(emulationActivity::finish)
+ }
+ }
+
+ @JvmStatic
+ @Keep
+ fun updateTouchPointer() {
+ val emulationActivity = emulationActivityRef.get()
+ if (emulationActivity == null) {
+ Log.warning("[NativeLibrary] EmulationActivity is null.")
+ } else {
+ emulationActivity.runOnUiThread(emulationActivity::initInputPointer)
+ }
+ }
+
+ @JvmStatic
+ @Keep
+ fun onTitleChanged() {
+ val emulationActivity = emulationActivityRef.get()
+ if (emulationActivity == null) {
+ Log.warning("[NativeLibrary] EmulationActivity is null.")
+ } else {
+ emulationActivity.runOnUiThread(emulationActivity::onTitleChanged)
+ }
+ }
+
+ @JvmStatic
+ @Keep
+ fun getRenderSurfaceScale(): Float {
+ val emulationActivity = emulationActivityRef.get()
+ if (emulationActivity == null) {
+ Log.warning("[NativeLibrary] EmulationActivity is null.")
+ return Resources.getSystem().displayMetrics.scaledDensity
+ }
+
+ return emulationActivity.resources.displayMetrics.scaledDensity
+ }
+
+ private fun checkGameMetadataValid() {
+ check(IsGameMetadataValid()) { "No game is running" }
+ }
+
+ private external fun IsEmulatingWiiUnchecked(): Boolean
+
+ private external fun GetCurrentGameIDUnchecked(): String
+
+ private external fun GetCurrentTitleDescriptionUnchecked(): String
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/AlertMessage.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/AlertMessage.kt
index 3c87b324f6..f79fddcdab 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/AlertMessage.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/AlertMessage.kt
@@ -16,6 +16,7 @@ import org.dolphinemu.dolphinemu.features.settings.model.NativeConfig
class AlertMessage : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val emulationActivity: EmulationActivity = NativeLibrary.getEmulationActivity()
+ ?: throw IllegalStateException("EmulationActivity missing while showing alert")
val args = requireArguments()
val title = args.getString(ARG_TITLE).orEmpty()
val message = args.getString(ARG_MESSAGE).orEmpty()
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.kt
index 04db24c03a..9cf87c3401 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.kt
@@ -57,9 +57,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
_binding = FragmentEmulationBinding.inflate(inflater, container, false)
return binding.root
@@ -98,8 +96,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
override fun onResume() {
super.onResume()
- if (NativeLibrary.IsGameMetadataValid())
+ if (NativeLibrary.IsGameMetadataValid()) {
inputOverlay?.refreshControls()
+ }
AfterDirectoryInitializationRunner().runWithLifecycle(this) {
run(emulationActivity!!.isActivityRecreated)
@@ -126,8 +125,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
fun toggleInputOverlayVisibility(settings: Settings?) {
BooleanSetting.MAIN_SHOW_INPUT_OVERLAY.setBoolean(
- settings!!,
- !BooleanSetting.MAIN_SHOW_INPUT_OVERLAY.boolean
+ settings!!, !BooleanSetting.MAIN_SHOW_INPUT_OVERLAY.boolean
)
inputOverlay?.refreshControls()
@@ -208,14 +206,20 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
val emulationThread = Thread({
if (loadPreviousTemporaryState) {
Log.debug("[EmulationFragment] Starting emulation thread from previous state.")
- NativeLibrary.Run(gamePaths, riivolution, temporaryStateFilePath, true)
+ val paths = requireNotNull(gamePaths) {
+ "Cannot start emulation without any game paths"
+ }
+ NativeLibrary.Run(paths, riivolution, temporaryStateFilePath, true)
}
if (launchSystemMenu) {
Log.debug("[EmulationFragment] Starting emulation thread for the Wii Menu.")
NativeLibrary.RunSystemMenu()
} else {
Log.debug("[EmulationFragment] Starting emulation thread.")
- NativeLibrary.Run(gamePaths, riivolution)
+ val paths = requireNotNull(gamePaths) {
+ "Cannot start emulation without any game paths"
+ }
+ NativeLibrary.Run(paths, riivolution)
}
EmulationActivity.stopIgnoringLaunchRequests()
}, "NativeEmulation")
@@ -239,9 +243,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
private const val KEY_SYSTEM_MENU = "systemMenu"
fun newInstance(
- gamePaths: Array<String>?,
- riivolution: Boolean,
- systemMenu: Boolean
+ gamePaths: Array<String>?, riivolution: Boolean, systemMenu: Boolean
): EmulationFragment {
val args = Bundle()
args.apply {