Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #9452 from JosJuice/android-wii-saves
Android: Add "Import Wii Save"
  • Loading branch information
leoetlino committed Jan 27, 2021
2 parents 7290cd0 + 12aa107 commit 96e3360
Show file tree
Hide file tree
Showing 17 changed files with 324 additions and 60 deletions.
Expand Up @@ -444,8 +444,6 @@ public static native void SetMotionSensorsEnabled(boolean accelerometerEnabled,

public static native void ReloadLoggerConfig();

public static native boolean InstallWAD(String file);

public static native boolean ConvertDiscImage(String inPath, String outPath, int platform,
int format, int blockSize, int compression, int compressionLevel, boolean scrub,
CompressCallback callback);
Expand Down
Expand Up @@ -175,21 +175,12 @@ public void launchFileListActivity()
}

@Override
public void launchOpenFileActivity()
public void launchOpenFileActivity(int requestCode)
{
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, MainPresenter.REQUEST_GAME_FILE);
}

@Override
public void launchInstallWAD()
{
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, MainPresenter.REQUEST_WAD_FILE);
startActivityForResult(intent, requestCode);
}

/**
Expand Down Expand Up @@ -229,6 +220,11 @@ protected void onActivityResult(int requestCode, int resultCode, Intent result)
FileBrowserHelper.runAfterExtensionCheck(this, uri, FileBrowserHelper.WAD_EXTENSION,
() -> mPresenter.installWAD(result.getData().toString()));
break;

case MainPresenter.REQUEST_WII_SAVE_FILE:
FileBrowserHelper.runAfterExtensionCheck(this, uri, FileBrowserHelper.BIN_EXTENSION,
() -> mPresenter.importWiiSave(result.getData().toString()));
break;
}
}
else
Expand Down
Expand Up @@ -7,31 +7,34 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.widget.Toast;

import androidx.appcompat.app.AlertDialog;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import org.dolphinemu.dolphinemu.BuildConfig;
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
import org.dolphinemu.dolphinemu.model.GameFileCache;
import org.dolphinemu.dolphinemu.services.GameFileCacheService;
import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner;
import org.dolphinemu.dolphinemu.utils.BooleanSupplier;
import org.dolphinemu.dolphinemu.utils.CompletableFuture;
import org.dolphinemu.dolphinemu.utils.ContentHandler;
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
import org.dolphinemu.dolphinemu.utils.WiiUtils;

import java.util.Arrays;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;

public final class MainPresenter
{
public static final int REQUEST_DIRECTORY = 1;
public static final int REQUEST_GAME_FILE = 2;
public static final int REQUEST_SD_FILE = 3;
public static final int REQUEST_WAD_FILE = 4;
public static final int REQUEST_WII_SAVE_FILE = 5;

private final MainView mView;
private final Context mContext;
Expand Down Expand Up @@ -92,11 +95,17 @@ public boolean handleOptionSelection(int itemId, Context context)
return true;

case R.id.menu_open_file:
mView.launchOpenFileActivity();
mView.launchOpenFileActivity(REQUEST_GAME_FILE);
return true;

case R.id.menu_install_wad:
new AfterDirectoryInitializationRunner().run(context, true, mView::launchInstallWAD);
new AfterDirectoryInitializationRunner().run(context, true,
() -> mView.launchOpenFileActivity(REQUEST_WAD_FILE));
return true;

case R.id.menu_import_wii_save:
new AfterDirectoryInitializationRunner().run(context, true,
() -> mView.launchOpenFileActivity(REQUEST_WII_SAVE_FILE));
return true;
}

Expand Down Expand Up @@ -150,32 +159,98 @@ public void onDirectorySelected(Intent result)
mDirToAdd = uri.toString();
}

public void installWAD(String file)
public void installWAD(String path)
{
runOnThreadAndShowResult(R.string.import_in_progress, () ->
{
boolean success = WiiUtils.installWAD(path);
int message = success ? R.string.wad_install_success : R.string.wad_install_failure;
return mContext.getResources().getString(message);
});
}

public void importWiiSave(String path)
{
final Activity mainPresenterActivity = (Activity) mContext;

AlertDialog dialog = new AlertDialog.Builder(mContext, R.style.DolphinDialogBase).create();
dialog.setTitle("Installing WAD");
dialog.setMessage("Installing...");
dialog.setCancelable(false);
dialog.show();
CompletableFuture<Boolean> canOverwriteFuture = new CompletableFuture<>();

Thread installWADThread = new Thread(() ->
runOnThreadAndShowResult(R.string.import_in_progress, () ->
{
if (NativeLibrary.InstallWAD(file))
BooleanSupplier canOverwrite = () ->
{
mainPresenterActivity.runOnUiThread(
() -> Toast.makeText(mContext, R.string.wad_install_success, Toast.LENGTH_SHORT)
.show());
}
else
mainPresenterActivity.runOnUiThread(() ->
{
AlertDialog.Builder builder =
new AlertDialog.Builder(mContext, R.style.DolphinDialogBase);
builder.setMessage(R.string.wii_save_exists);
builder.setCancelable(false);
builder.setPositiveButton(R.string.yes, (dialog, i) -> canOverwriteFuture.complete(true));
builder.setNegativeButton(R.string.no, (dialog, i) -> canOverwriteFuture.complete(false));
builder.show();
});

try
{
return canOverwriteFuture.get();
}
catch (ExecutionException | InterruptedException e)
{
// Shouldn't happen
throw new RuntimeException(e);
}
};

int result = WiiUtils.importWiiSave(path, canOverwrite);

int message;
switch (result)
{
mainPresenterActivity.runOnUiThread(
() -> Toast.makeText(mContext, R.string.wad_install_failure, Toast.LENGTH_SHORT)
.show());
case WiiUtils.RESULT_SUCCESS:
message = R.string.wii_save_import_success;
break;
case WiiUtils.RESULT_CORRUPTED_SOURCE:
message = R.string.wii_save_import_corruped_source;
break;
case WiiUtils.RESULT_TITLE_MISSING:
message = R.string.wii_save_import_title_missing;
break;
case WiiUtils.RESULT_CANCELLED:
return null;
default:
message = R.string.wii_save_import_error;
break;
}
mainPresenterActivity.runOnUiThread(dialog::dismiss);
}, "InstallWAD");
installWADThread.start();
return mContext.getResources().getString(message);
});
}

private void runOnThreadAndShowResult(int progressMessage, Supplier<String> f)
{
final Activity mainPresenterActivity = (Activity) mContext;

AlertDialog progressDialog = new AlertDialog.Builder(mContext, R.style.DolphinDialogBase)
.create();
progressDialog.setTitle(progressMessage);
progressDialog.setCancelable(false);
progressDialog.show();

new Thread(() ->
{
String result = f.get();
mainPresenterActivity.runOnUiThread(() ->
{
progressDialog.dismiss();

if (result != null)
{
AlertDialog.Builder builder =
new AlertDialog.Builder(mContext, R.style.DolphinDialogBase);
builder.setMessage(result);
builder.setPositiveButton(R.string.ok, (dialog, i) -> dialog.dismiss());
builder.show();
}
});
}, mContext.getResources().getString(progressMessage)).start();
}
}
Expand Up @@ -21,9 +21,7 @@

void launchFileListActivity();

void launchOpenFileActivity();

void launchInstallWAD();
void launchOpenFileActivity(int requestCode);

/**
* To be called when the game file cache is updated.
Expand Down
Expand Up @@ -180,21 +180,12 @@ public void launchFileListActivity()
}

@Override
public void launchOpenFileActivity()
public void launchOpenFileActivity(int requestCode)
{
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, MainPresenter.REQUEST_GAME_FILE);
}

@Override
public void launchInstallWAD()
{
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, MainPresenter.REQUEST_WAD_FILE);
startActivityForResult(intent, requestCode);
}

@Override
Expand Down Expand Up @@ -253,6 +244,11 @@ protected void onActivityResult(int requestCode, int resultCode, Intent result)
FileBrowserHelper.runAfterExtensionCheck(this, uri, FileBrowserHelper.WAD_EXTENSION,
() -> mPresenter.installWAD(result.getData().toString()));
break;

case MainPresenter.REQUEST_WII_SAVE_FILE:
FileBrowserHelper.runAfterExtensionCheck(this, uri, FileBrowserHelper.BIN_EXTENSION,
() -> mPresenter.importWiiSave(result.getData().toString()));
break;
}
}
else
Expand Down Expand Up @@ -353,6 +349,10 @@ private ListRow buildSettingsRow()
R.drawable.ic_folder,
R.string.grid_menu_install_wad));

rowItems.add(new TvSettingsItem(R.id.menu_import_wii_save,
R.drawable.ic_folder,
R.string.grid_menu_import_wii_save));

// Create a header for this row.
HeaderItem header =
new HeaderItem(R.string.preferences_settings, getString(R.string.preferences_settings));
Expand Down
@@ -0,0 +1,6 @@
package org.dolphinemu.dolphinemu.utils;

public interface BooleanSupplier
{
boolean get();
}
@@ -0,0 +1,95 @@
package org.dolphinemu.dolphinemu.utils;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* Simplified re-implementation of a subset of {@link java.util.concurrent.CompletableFuture}.
* Replace this class with that class once we have full Java 8 support (once we require API 24).
*/
public class CompletableFuture<T> implements Future<T>
{
private final Lock lock = new ReentrantLock();
private final Condition done = lock.newCondition();

private boolean isDone = false;
private T result = null;

@Override
public boolean cancel(boolean mayInterruptIfRunning)
{
throw new UnsupportedOperationException();
}

@Override
public boolean isCancelled()
{
return false;
}

@Override
public boolean isDone()
{
return isDone;
}

@Override
public T get() throws ExecutionException, InterruptedException
{
lock.lock();
try
{
while (!isDone)
done.await();

return result;
}
finally
{
lock.unlock();
}
}

@Override
public T get(long timeout, TimeUnit unit)
throws ExecutionException, InterruptedException, TimeoutException
{
lock.lock();
try
{
while (!isDone)
{
if (!done.await(timeout, unit))
throw new TimeoutException();
}

return result;
}
finally
{
lock.unlock();
}
}

public boolean complete(T value)
{
lock.lock();
try
{
boolean wasDone = isDone;
result = value;
isDone = true;
done.signalAll();
return !wasDone;
}
finally
{
lock.unlock();
}
}
}
Expand Up @@ -37,6 +37,9 @@
GAME_LIKE_EXTENSIONS.add("dff");
}

public static final HashSet<String> BIN_EXTENSION = new HashSet<>(Collections.singletonList(
"bin"));

public static final HashSet<String> RAW_EXTENSION = new HashSet<>(Collections.singletonList(
"raw"));

Expand Down

0 comments on commit 96e3360

Please sign in to comment.