summaryrefslogtreecommitdiff
path: root/Source/Android/app/src/main/java
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2022-01-22 14:46:42 -0500
committerGitHub <noreply@github.com>2022-01-22 14:46:42 -0500
commit237947e2f139a033da71e733c5e6e24d61b5142d (patch)
treef7cdc46f40fa9f829892d6b2cbffbd07d9e865e4 /Source/Android/app/src/main/java
parent7b8e846d0ab1a95c4070c3d89e38180895e536c6 (diff)
parent55378cab393547538275c56bae718a37a3f69737 (diff)
Merge pull request #10369 from Simonx22/android-online-system-update-2
Android: Add online system update functionality
Diffstat (limited to 'Source/Android/app/src/main/java')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java5
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java48
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/OnlineUpdateProgressBarDialogFragment.java110
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/OnlineUpdateRegionSelectDialogFragment.java42
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/OnlineUpdateResultFragment.java105
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/SystemMenuNotInstalledDialogFragment.java34
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/SystemUpdateViewModel.java90
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java13
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java13
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java60
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java8
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUpdateCallback.java11
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java16
13 files changed, 541 insertions, 14 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
index 974832878e..dd2c4e8407 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java
@@ -387,6 +387,11 @@ public final class NativeLibrary
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
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
index 815b5b7396..3b7838a814 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
@@ -9,7 +9,6 @@ import android.content.SharedPreferences;
import android.graphics.Rect;
import android.os.Bundle;
import android.preference.PreferenceManager;
-import android.text.TextUtils;
import android.util.SparseIntArray;
import android.view.InputDevice;
import android.view.KeyEvent;
@@ -80,12 +79,14 @@ public final class EmulationActivity extends AppCompatActivity
private boolean activityRecreated;
private String[] mPaths;
private boolean mRiivolution;
+ private boolean mLaunchSystemMenu;
private boolean mIgnoreWarnings;
private static boolean sUserPausedEmulation;
private boolean mMenuToastShown;
public static final String EXTRA_SELECTED_GAMES = "SelectedGames";
public static final String EXTRA_RIIVOLUTION = "Riivolution";
+ public static final String EXTRA_SYSTEM_MENU = "SystemMenu";
public static final String EXTRA_IGNORE_WARNINGS = "IgnoreWarnings";
public static final String EXTRA_USER_PAUSED_EMULATION = "sUserPausedEmulation";
public static final String EXTRA_MENU_TOAST_SHOWN = "MenuToastShown";
@@ -171,11 +172,9 @@ public final class EmulationActivity extends AppCompatActivity
launch(activity, new String[]{filePath}, riivolution);
}
- public static void launch(FragmentActivity activity, String[] filePaths, boolean riivolution)
+ private static void performLaunchChecks(FragmentActivity activity,
+ Runnable continueCallback)
{
- if (sIgnoreLaunchRequests)
- return;
-
new AfterDirectoryInitializationRunner().runWithLifecycle(activity, true, () ->
{
if (FileBrowserHelper.isPathEmptyOrValid(StringSetting.MAIN_DEFAULT_ISO) &&
@@ -185,7 +184,7 @@ public final class EmulationActivity extends AppCompatActivity
FileBrowserHelper.isPathEmptyOrValid(StringSetting.MAIN_RESOURCEPACK_PATH) &&
FileBrowserHelper.isPathEmptyOrValid(StringSetting.MAIN_SD_PATH))
{
- launchWithoutChecks(activity, filePaths, riivolution);
+ continueCallback.run();
}
else
{
@@ -194,12 +193,44 @@ public final class EmulationActivity extends AppCompatActivity
builder.setPositiveButton(R.string.yes, (dialogInterface, i) ->
SettingsActivity.launch(activity, MenuTag.CONFIG_PATHS));
builder.setNeutralButton(R.string.continue_anyway, (dialogInterface, i) ->
- launchWithoutChecks(activity, filePaths, riivolution));
+ continueCallback.run());
builder.show();
}
});
}
+
+ public static void launchSystemMenu(FragmentActivity activity)
+ {
+ if (sIgnoreLaunchRequests)
+ return;
+
+ performLaunchChecks(activity, () ->
+ {
+ launchSystemMenuWithoutChecks(activity);
+ });
+ }
+
+ public static void launch(FragmentActivity activity, String[] filePaths, boolean riivolution)
+ {
+ if (sIgnoreLaunchRequests)
+ return;
+
+ performLaunchChecks(activity, () ->
+ {
+ launchWithoutChecks(activity, filePaths, riivolution);
+ });
+ }
+
+ private static void launchSystemMenuWithoutChecks(FragmentActivity activity)
+ {
+ sIgnoreLaunchRequests = true;
+
+ Intent launcher = new Intent(activity, EmulationActivity.class);
+ launcher.putExtra(EmulationActivity.EXTRA_SYSTEM_MENU, true);
+ activity.startActivity(launcher);
+ }
+
private static void launchWithoutChecks(FragmentActivity activity, String[] filePaths,
boolean riivolution)
{
@@ -256,6 +287,7 @@ public final class EmulationActivity extends AppCompatActivity
Intent gameToEmulate = getIntent();
mPaths = gameToEmulate.getStringArrayExtra(EXTRA_SELECTED_GAMES);
mRiivolution = gameToEmulate.getBooleanExtra(EXTRA_RIIVOLUTION, false);
+ mLaunchSystemMenu = gameToEmulate.getBooleanExtra(EXTRA_SYSTEM_MENU, false);
mIgnoreWarnings = gameToEmulate.getBooleanExtra(EXTRA_IGNORE_WARNINGS, false);
sUserPausedEmulation = gameToEmulate.getBooleanExtra(EXTRA_USER_PAUSED_EMULATION, false);
mMenuToastShown = false;
@@ -288,7 +320,7 @@ public final class EmulationActivity extends AppCompatActivity
.findFragmentById(R.id.frame_emulation_fragment);
if (mEmulationFragment == null)
{
- mEmulationFragment = EmulationFragment.newInstance(mPaths, mRiivolution);
+ mEmulationFragment = EmulationFragment.newInstance(mPaths, mRiivolution, mLaunchSystemMenu);
getSupportFragmentManager().beginTransaction()
.add(R.id.frame_emulation_fragment, mEmulationFragment)
.commit();
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/OnlineUpdateProgressBarDialogFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/OnlineUpdateProgressBarDialogFragment.java
new file mode 100644
index 0000000000..7130b09f00
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/OnlineUpdateProgressBarDialogFragment.java
@@ -0,0 +1,110 @@
+package org.dolphinemu.dolphinemu.features.sysupdate.ui;
+
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.pm.ActivityInfo;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
+import androidx.lifecycle.ViewModelProvider;
+
+import org.dolphinemu.dolphinemu.R;
+
+public class OnlineUpdateProgressBarDialogFragment extends DialogFragment
+{
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState)
+ {
+ // Store the current orientation to be restored later
+ final int orientation = getActivity().getRequestedOrientation();
+ // Rotating the device while the update is running can result in a title failing to import.
+ getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
+
+ SystemUpdateViewModel viewModel =
+ new ViewModelProvider(requireActivity()).get(SystemUpdateViewModel.class);
+
+ ProgressDialog progressDialog = new ProgressDialog(requireContext());
+ progressDialog.setTitle(getString(R.string.updating));
+ // We need to set the message to something here, otherwise the text will not appear when we set it later.
+ progressDialog.setMessage("");
+ progressDialog.setButton(Dialog.BUTTON_NEGATIVE, getString(R.string.cancel), (dialog, i) ->
+ {
+ });
+ progressDialog.setOnShowListener((dialogInterface) ->
+ {
+ // By default, the ProgressDialog will immediately dismiss itself upon a button being pressed.
+ // Setting the OnClickListener again after the dialog is shown overrides this behavior.
+ progressDialog.getButton(Dialog.BUTTON_NEGATIVE).setOnClickListener((view) ->
+ {
+ viewModel.setCanceled();
+ });
+ });
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+
+ viewModel.getProgressData().observe(this, (@Nullable Integer progress) ->
+ {
+ progressDialog.setProgress(progress.intValue());
+ });
+
+ viewModel.getTotalData().observe(this, (@Nullable Integer total) ->
+ {
+ if (total == 0)
+ {
+ return;
+ }
+
+ progressDialog.setMax(total.intValue());
+ });
+
+ viewModel.getTitleIdData().observe(this, (@Nullable Long titleId) ->
+ {
+ progressDialog.setMessage(getString(R.string.updating_message, titleId));
+ });
+
+ viewModel.getResultData().observe(this, (@Nullable Integer result) ->
+ {
+ if (result == -1)
+ {
+ // This is the default value, ignore
+ return;
+ }
+
+ OnlineUpdateResultFragment progressBarFragment = new OnlineUpdateResultFragment();
+ progressBarFragment.show(getParentFragmentManager(), "OnlineUpdateResultFragment");
+
+ getActivity().setRequestedOrientation(orientation);
+
+ dismiss();
+ });
+
+ if (savedInstanceState == null)
+ {
+ final String region;
+ int selectedItem = viewModel.getRegion();
+
+ switch (selectedItem)
+ {
+ case 0:
+ region = "EUR";
+ break;
+ case 1:
+ region = "JPN";
+ break;
+ case 2:
+ region = "KOR";
+ break;
+ case 3:
+ region = "USA";
+ break;
+ default:
+ region = "";
+ break;
+ }
+ viewModel.startUpdate(region);
+ }
+ return progressDialog;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/OnlineUpdateRegionSelectDialogFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/OnlineUpdateRegionSelectDialogFragment.java
new file mode 100644
index 0000000000..198008d288
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/OnlineUpdateRegionSelectDialogFragment.java
@@ -0,0 +1,42 @@
+package org.dolphinemu.dolphinemu.features.sysupdate.ui;
+
+import android.app.Dialog;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.lifecycle.ViewModelProvider;
+
+import org.dolphinemu.dolphinemu.R;
+
+public class OnlineUpdateRegionSelectDialogFragment extends DialogFragment
+{
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState)
+ {
+ String[] items = {getString(R.string.europe), getString(
+ R.string.japan), getString(R.string.korea), getString(R.string.united_states)};
+ int checkedItem = -1;
+
+ return new AlertDialog.Builder(requireContext(), R.style.DolphinDialogBase)
+ .setTitle(R.string.region_select_title)
+ .setSingleChoiceItems(items, checkedItem, (dialog, which) ->
+ {
+ SystemUpdateViewModel viewModel =
+ new ViewModelProvider(requireActivity()).get(SystemUpdateViewModel.class);
+ viewModel.setRegion(which);
+
+ OnlineUpdateProgressBarDialogFragment progressBarFragment =
+ new OnlineUpdateProgressBarDialogFragment();
+ progressBarFragment
+ .show(getParentFragmentManager(), "OnlineUpdateProgressBarDialogFragment");
+ progressBarFragment.setCancelable(false);
+
+ dismiss();
+ })
+ .create();
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/OnlineUpdateResultFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/OnlineUpdateResultFragment.java
new file mode 100644
index 0000000000..e1f7557944
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/OnlineUpdateResultFragment.java
@@ -0,0 +1,105 @@
+package org.dolphinemu.dolphinemu.features.sysupdate.ui;
+
+import android.app.Dialog;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.lifecycle.ViewModelProvider;
+
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.utils.WiiUtils;
+
+public class OnlineUpdateResultFragment extends DialogFragment
+{
+ private int mResult;
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState)
+ {
+ SystemUpdateViewModel viewModel =
+ new ViewModelProvider(requireActivity()).get(SystemUpdateViewModel.class);
+ if (savedInstanceState == null)
+ {
+ mResult = viewModel.getResultData().getValue().intValue();
+ viewModel.clear();
+ }
+ else
+ {
+ mResult = savedInstanceState.getInt("result");
+ }
+
+ String message;
+ switch (mResult)
+ {
+ case WiiUtils.UPDATE_RESULT_SUCCESS:
+ message = getString(R.string.update_success);
+ break;
+ case WiiUtils.UPDATE_RESULT_ALREADY_UP_TO_DATE:
+ message = getString(R.string.already_up_to_date);
+ break;
+ case WiiUtils.UPDATE_RESULT_REGION_MISMATCH:
+ message = getString(R.string.region_mismatch);
+ break;
+ case WiiUtils.UPDATE_RESULT_MISSING_UPDATE_PARTITION:
+ message = getString(R.string.missing_update_partition);
+ break;
+ case WiiUtils.UPDATE_RESULT_DISC_READ_FAILED:
+ message = getString(R.string.disc_read_failed);
+ break;
+ case WiiUtils.UPDATE_RESULT_SERVER_FAILED:
+ message = getString(R.string.server_failed);
+ break;
+ case WiiUtils.UPDATE_RESULT_DOWNLOAD_FAILED:
+ message = getString(R.string.download_failed);
+ break;
+ case WiiUtils.UPDATE_RESULT_IMPORT_FAILED:
+ message = getString(R.string.import_failed);
+ break;
+ case WiiUtils.UPDATE_RESULT_CANCELLED:
+ message = getString(R.string.update_cancelled);
+ break;
+ default:
+ throw new IllegalStateException("Unexpected value: " + mResult);
+ }
+
+ String title;
+ switch (mResult)
+ {
+ case WiiUtils.UPDATE_RESULT_SUCCESS:
+ case WiiUtils.UPDATE_RESULT_ALREADY_UP_TO_DATE:
+ title = getString(R.string.update_success_title);
+ break;
+ case WiiUtils.UPDATE_RESULT_REGION_MISMATCH:
+ case WiiUtils.UPDATE_RESULT_MISSING_UPDATE_PARTITION:
+ case WiiUtils.UPDATE_RESULT_DISC_READ_FAILED:
+ case WiiUtils.UPDATE_RESULT_SERVER_FAILED:
+ case WiiUtils.UPDATE_RESULT_DOWNLOAD_FAILED:
+ case WiiUtils.UPDATE_RESULT_IMPORT_FAILED:
+ title = getString(R.string.update_failed_title);
+ break;
+ case WiiUtils.UPDATE_RESULT_CANCELLED:
+ title = getString(R.string.update_cancelled_title);
+ break;
+ default:
+ throw new IllegalStateException("Unexpected value: " + mResult);
+ }
+
+ return new AlertDialog.Builder(requireContext(), R.style.DolphinDialogBase)
+ .setTitle(title)
+ .setMessage(message)
+ .setPositiveButton(R.string.ok, (dialog, which) ->
+ {
+ dismiss();
+ })
+ .create();
+ }
+
+ @Override
+ public void onSaveInstanceState(@NonNull Bundle outState)
+ {
+ super.onSaveInstanceState(outState);
+ outState.putInt("result", mResult);
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/SystemMenuNotInstalledDialogFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/SystemMenuNotInstalledDialogFragment.java
new file mode 100644
index 0000000000..b70e7682b7
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/SystemMenuNotInstalledDialogFragment.java
@@ -0,0 +1,34 @@
+package org.dolphinemu.dolphinemu.features.sysupdate.ui;
+
+import android.app.Dialog;
+import android.os.Bundle;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.FragmentManager;
+
+import org.dolphinemu.dolphinemu.R;
+
+public class SystemMenuNotInstalledDialogFragment extends DialogFragment
+{
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState)
+ {
+ return new AlertDialog.Builder(requireContext(), R.style.DolphinDialogBase)
+ .setTitle(R.string.system_menu_not_installed_title)
+ .setMessage(R.string.system_menu_not_installed_message)
+ .setPositiveButton(R.string.yes, (dialog, which) ->
+ {
+ FragmentManager fragmentManager = getParentFragmentManager();
+ OnlineUpdateRegionSelectDialogFragment dialogFragment =
+ new OnlineUpdateRegionSelectDialogFragment();
+ dialogFragment.show(fragmentManager, "OnlineUpdateRegionSelectDialogFragment");
+ dismiss();
+ })
+ .setNegativeButton(R.string.no, (dialog, which) ->
+ {
+ dismiss();
+ })
+ .create();
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/SystemUpdateViewModel.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/SystemUpdateViewModel.java
new file mode 100644
index 0000000000..ced570f8c3
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/sysupdate/ui/SystemUpdateViewModel.java
@@ -0,0 +1,90 @@
+package org.dolphinemu.dolphinemu.features.sysupdate.ui;
+
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.ViewModel;
+
+import org.dolphinemu.dolphinemu.utils.WiiUtils;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class SystemUpdateViewModel extends ViewModel
+{
+ private static final ExecutorService executor = Executors.newFixedThreadPool(1);
+
+ private final MutableLiveData<Integer> mProgressData = new MutableLiveData<>();
+ private final MutableLiveData<Integer> mTotalData = new MutableLiveData<>();
+ private final MutableLiveData<Long> mTitleIdData = new MutableLiveData<>();
+ private final MutableLiveData<Integer> mResultData = new MutableLiveData<>();
+
+ private boolean mCanceled = false;
+ private int mRegion;
+
+ public SystemUpdateViewModel()
+ {
+ clear();
+ }
+
+ public void setRegion(int region)
+ {
+ mRegion = region;
+ }
+
+ public int getRegion()
+ {
+ return mRegion;
+ }
+
+ public MutableLiveData<Integer> getProgressData()
+ {
+ return mProgressData;
+ }
+
+ public MutableLiveData<Integer> getTotalData()
+ {
+ return mTotalData;
+ }
+
+ public MutableLiveData<Long> getTitleIdData()
+ {
+ return mTitleIdData;
+ }
+
+ public MutableLiveData<Integer> getResultData()
+ {
+ return mResultData;
+ }
+
+ public void setCanceled()
+ {
+ mCanceled = true;
+ }
+
+ public void startUpdate(String region)
+ {
+ mCanceled = false;
+
+ executor.execute(() ->
+ {
+ int result = WiiUtils.doOnlineUpdate(region, ((processed, total, titleId) ->
+ {
+ mProgressData.postValue(processed);
+ mTotalData.postValue(total);
+ mTitleIdData.postValue(titleId);
+
+ return !mCanceled;
+ }));
+
+ mResultData.postValue(result);
+ });
+ }
+
+ public void clear()
+ {
+ mProgressData.setValue(0);
+ mTotalData.setValue(0);
+ mTitleIdData.setValue(0l);
+ mResultData.setValue(-1);
+ mCanceled = false;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java
index 7f1e158830..01d6ab6719 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java
@@ -6,7 +6,6 @@ import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.LayoutInflater;
-import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
@@ -30,6 +29,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
{
private static final String KEY_GAMEPATHS = "gamepaths";
private static final String KEY_RIIVOLUTION = "riivolution";
+ private static final String KEY_SYSTEM_MENU = "systemMenu";
private InputOverlay mInputOverlay;
@@ -37,14 +37,17 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
private boolean mRiivolution;
private boolean mRunWhenSurfaceIsValid;
private boolean mLoadPreviousTemporaryState;
+ private boolean mLaunchSystemMenu;
private EmulationActivity activity;
- public static EmulationFragment newInstance(String[] gamePaths, boolean riivolution)
+ public static EmulationFragment newInstance(String[] gamePaths, boolean riivolution,
+ boolean systemMenu)
{
Bundle args = new Bundle();
args.putStringArray(KEY_GAMEPATHS, gamePaths);
args.putBoolean(KEY_RIIVOLUTION, riivolution);
+ args.putBoolean(KEY_SYSTEM_MENU, systemMenu);
EmulationFragment fragment = new EmulationFragment();
fragment.setArguments(args);
@@ -77,6 +80,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
mGamePaths = getArguments().getStringArray(KEY_GAMEPATHS);
mRiivolution = getArguments().getBoolean(KEY_RIIVOLUTION);
+ mLaunchSystemMenu = getArguments().getBoolean(KEY_SYSTEM_MENU);
}
/**
@@ -270,6 +274,11 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
Log.debug("[EmulationFragment] Starting emulation thread from previous state.");
NativeLibrary.Run(mGamePaths, mRiivolution, getTemporaryStateFilePath(), true);
}
+ if (mLaunchSystemMenu)
+ {
+ Log.debug("[EmulationFragment] Starting emulation thread for the Wii Menu.");
+ NativeLibrary.RunSystemMenu();
+ }
else
{
Log.debug("[EmulationFragment] Starting emulation thread.");
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java
index 2b9b8defda..711f7d36de 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java
@@ -14,6 +14,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
+import androidx.lifecycle.ViewModelProvider;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.viewpager.widget.ViewPager;
@@ -27,6 +28,9 @@ import org.dolphinemu.dolphinemu.features.settings.model.IntSetting;
import org.dolphinemu.dolphinemu.features.settings.model.NativeConfig;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
+import org.dolphinemu.dolphinemu.features.sysupdate.ui.OnlineUpdateProgressBarDialogFragment;
+import org.dolphinemu.dolphinemu.features.sysupdate.ui.SystemMenuNotInstalledDialogFragment;
+import org.dolphinemu.dolphinemu.features.sysupdate.ui.SystemUpdateViewModel;
import org.dolphinemu.dolphinemu.services.GameFileCacheManager;
import org.dolphinemu.dolphinemu.ui.platform.Platform;
import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView;
@@ -36,6 +40,7 @@ import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
import org.dolphinemu.dolphinemu.utils.StartupHandler;
+import org.dolphinemu.dolphinemu.utils.WiiUtils;
/**
* The main Activity of the Lollipop style UI. Manages several PlatformGamesFragments, which
@@ -142,6 +147,14 @@ public final class MainActivity extends AppCompatActivity
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_game_grid, menu);
+
+ if (WiiUtils.isSystemMenuInstalled())
+ {
+ menu.findItem(R.id.menu_load_wii_system_menu).setTitle(
+ getString(R.string.grid_menu_load_wii_system_menu_installed,
+ WiiUtils.getSystemMenuVersion()));
+ }
+
return true;
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java
index 76f53ddd72..b95b35331f 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java
@@ -3,18 +3,23 @@
package org.dolphinemu.dolphinemu.ui.main;
import android.content.ContentResolver;
-import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import androidx.appcompat.app.AlertDialog;
-import androidx.core.app.ComponentActivity;
+import androidx.activity.ComponentActivity;
+import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Observer;
+import androidx.lifecycle.ViewModelProvider;
import org.dolphinemu.dolphinemu.BuildConfig;
import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
+import org.dolphinemu.dolphinemu.features.sysupdate.ui.OnlineUpdateProgressBarDialogFragment;
+import org.dolphinemu.dolphinemu.features.sysupdate.ui.SystemMenuNotInstalledDialogFragment;
+import org.dolphinemu.dolphinemu.features.sysupdate.ui.SystemUpdateViewModel;
import org.dolphinemu.dolphinemu.model.GameFileCache;
import org.dolphinemu.dolphinemu.services.GameFileCacheManager;
import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner;
@@ -40,10 +45,10 @@ public final class MainPresenter
private static boolean sShouldRescanLibrary = true;
private final MainView mView;
- private final ComponentActivity mActivity;
+ private final FragmentActivity mActivity;
private String mDirToAdd;
- public MainPresenter(MainView view, ComponentActivity activity)
+ public MainPresenter(MainView view, FragmentActivity activity)
{
mView = view;
mActivity = activity;
@@ -94,6 +99,14 @@ public final class MainPresenter
mView.launchOpenFileActivity(REQUEST_GAME_FILE);
return true;
+ case R.id.menu_load_wii_system_menu:
+ launchWiiSystemMenu();
+ return true;
+
+ case R.id.menu_online_system_update:
+ launchOnlineUpdate();
+ return true;
+
case R.id.menu_install_wad:
new AfterDirectoryInitializationRunner().runWithLifecycle(activity, true,
() -> mView.launchOpenFileActivity(REQUEST_WAD_FILE));
@@ -287,4 +300,43 @@ public final class MainPresenter
{
sShouldRescanLibrary = false;
}
+
+ private void launchOnlineUpdate()
+ {
+ if (WiiUtils.isSystemMenuInstalled())
+ {
+ SystemUpdateViewModel viewModel =
+ new ViewModelProvider(mActivity).get(SystemUpdateViewModel.class);
+ viewModel.setRegion(-1);
+ OnlineUpdateProgressBarDialogFragment progressBarFragment =
+ new OnlineUpdateProgressBarDialogFragment();
+ progressBarFragment
+ .show(mActivity.getSupportFragmentManager(), "OnlineUpdateProgressBarDialogFragment");
+ progressBarFragment.setCancelable(false);
+ }
+ else
+ {
+ SystemMenuNotInstalledDialogFragment dialogFragment =
+ new SystemMenuNotInstalledDialogFragment();
+ dialogFragment
+ .show(mActivity.getSupportFragmentManager(), "SystemMenuNotInstalledDialogFragment");
+ }
+ }
+
+ private void launchWiiSystemMenu()
+ {
+ WiiUtils.isSystemMenuInstalled();
+
+ if (WiiUtils.isSystemMenuInstalled())
+ {
+ EmulationActivity.launchSystemMenu(mActivity);
+ }
+ else
+ {
+ SystemMenuNotInstalledDialogFragment dialogFragment =
+ new SystemMenuNotInstalledDialogFragment();
+ dialogFragment
+ .show(mActivity.getSupportFragmentManager(), "SystemMenuNotInstalledDialogFragment");
+ }
+ }
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java
index 58f3bbafb7..77ad01ecf3 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java
@@ -378,6 +378,10 @@ public final class TvMainActivity extends FragmentActivity
R.drawable.ic_folder,
R.string.grid_menu_install_wad));
+ rowItems.add(new TvSettingsItem(R.id.menu_load_wii_system_menu,
+ R.drawable.ic_folder,
+ R.string.grid_menu_load_wii_system_menu));
+
rowItems.add(new TvSettingsItem(R.id.menu_import_wii_save,
R.drawable.ic_folder,
R.string.grid_menu_import_wii_save));
@@ -386,6 +390,10 @@ public final class TvMainActivity extends FragmentActivity
R.drawable.ic_folder,
R.string.grid_menu_import_nand_backup));
+ rowItems.add(new TvSettingsItem(R.id.menu_online_system_update,
+ R.drawable.ic_folder,
+ R.string.grid_menu_online_system_update));
+
// Create a header for this row.
HeaderItem header = new HeaderItem(R.string.settings, getString(R.string.settings));
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUpdateCallback.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUpdateCallback.java
new file mode 100644
index 0000000000..cd7096974e
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUpdateCallback.java
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.utils;
+
+import androidx.annotation.Keep;
+
+public interface WiiUpdateCallback
+{
+ @Keep
+ boolean run(int processed, int total, long titleId);
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java
index cd92e21cb5..42e11a67c0 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java
@@ -10,9 +10,25 @@ public final class WiiUtils
public static final int RESULT_CORRUPTED_SOURCE = 3;
public static final int RESULT_TITLE_MISSING = 4;
+ public static final int UPDATE_RESULT_SUCCESS = 0;
+ public static final int UPDATE_RESULT_ALREADY_UP_TO_DATE = 1;
+ public static final int UPDATE_RESULT_REGION_MISMATCH = 2;
+ public static final int UPDATE_RESULT_MISSING_UPDATE_PARTITION = 3;
+ public static final int UPDATE_RESULT_DISC_READ_FAILED = 4;
+ public static final int UPDATE_RESULT_SERVER_FAILED = 5;
+ public static final int UPDATE_RESULT_DOWNLOAD_FAILED = 6;
+ public static final int UPDATE_RESULT_IMPORT_FAILED = 7;
+ public static final int UPDATE_RESULT_CANCELLED = 8;
+
public static native boolean installWAD(String file);
public static native int importWiiSave(String file, BooleanSupplier canOverwrite);
public static native void importNANDBin(String file);
+
+ public static native int doOnlineUpdate(String region, WiiUpdateCallback callback);
+
+ public static native boolean isSystemMenuInstalled();
+
+ public static native String getSystemMenuVersion();
}