@@ -0,0 +1,14 @@
package org.dolphinemu.dolphinemu.utils;

public final class WiiUtils
{
public static final int RESULT_SUCCESS = 0;
public static final int RESULT_ERROR = 1;
public static final int RESULT_CANCELLED = 2;
public static final int RESULT_CORRUPTED_SOURCE = 3;
public static final int RESULT_TITLE_MISSING = 4;

public static native boolean installWAD(String file);

public static native int importWiiSave(String file, BooleanSupplier canOverwrite);
}
5 changes: 5 additions & 0 deletions Source/Android/app/src/main/res/menu/menu_game_grid.xml
Expand Up @@ -25,4 +25,9 @@
android:title="@string/grid_menu_install_wad"
app:showAsAction="never"/>

<item
android:id="@+id/menu_import_wii_save"
android:title="@string/grid_menu_import_wii_save"
app:showAsAction="never"/>

</menu>
7 changes: 7 additions & 0 deletions Source/Android/app/src/main/res/values/strings.xml
Expand Up @@ -329,8 +329,15 @@
<string name="grid_menu_refresh">Refresh Library</string>
<string name="grid_menu_open_file">Open File</string>
<string name="grid_menu_install_wad">Install WAD</string>
<string name="grid_menu_import_wii_save">Import Wii Save</string>
<string name="import_in_progress">Importing...</string>
<string name="wad_install_success">Successfully installed this title to the NAND.</string>
<string name="wad_install_failure">Failed to install this title to the NAND.</string>
<string name="wii_save_exists">Save data for this title already exists in the NAND. Consider backing up the current data before overwriting.\nOverwrite now?</string>
<string name="wii_save_import_success">Successfully imported save file.</string>
<string name="wii_save_import_error">Failed to import save file. Your NAND may be corrupt, or something is preventing access to files within it.</string>
<string name="wii_save_import_corruped_source">Failed to import save file. The given file appears to be corrupted or is not a valid Wii save.</string>
<string name="wii_save_import_title_missing">Failed to import save file. Please launch the game once, then try again.</string>

<!-- Game Properties Screen -->
<string name="properties_details">Details</string>
Expand Down
13 changes: 13 additions & 0 deletions Source/Android/jni/AndroidCommon/IDCache.cpp
Expand Up @@ -56,6 +56,9 @@ static jmethodID s_network_helper_get_network_ip_address;
static jmethodID s_network_helper_get_network_prefix_length;
static jmethodID s_network_helper_get_network_gateway;

static jclass s_boolean_supplier_class;
static jmethodID s_boolean_supplier_get;

namespace IDCache
{
JNIEnv* GetEnvForThread()
Expand Down Expand Up @@ -261,6 +264,11 @@ jmethodID GetNetworkHelperGetNetworkGateway()
return s_network_helper_get_network_gateway;
}

jmethodID GetBooleanSupplierGet()
{
return s_boolean_supplier_get;
}

} // namespace IDCache

#ifdef __cplusplus
Expand Down Expand Up @@ -361,6 +369,11 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
s_network_helper_get_network_gateway =
env->GetStaticMethodID(s_network_helper_class, "GetNetworkGateway", "()I");

const jclass boolean_supplier_class =
env->FindClass("org/dolphinemu/dolphinemu/utils/BooleanSupplier");
s_boolean_supplier_class = reinterpret_cast<jclass>(env->NewGlobalRef(boolean_supplier_class));
s_boolean_supplier_get = env->GetMethodID(s_boolean_supplier_class, "get", "()Z");

return JNI_VERSION;
}

Expand Down
2 changes: 2 additions & 0 deletions Source/Android/jni/AndroidCommon/IDCache.h
Expand Up @@ -56,4 +56,6 @@ jmethodID GetNetworkHelperGetNetworkIpAddress();
jmethodID GetNetworkHelperGetNetworkPrefixLength();
jmethodID GetNetworkHelperGetNetworkGateway();

jmethodID GetBooleanSupplierGet();

} // namespace IDCache
1 change: 1 addition & 0 deletions Source/Android/jni/CMakeLists.txt
Expand Up @@ -5,6 +5,7 @@ add_library(main SHARED
IniFile.cpp
MainAndroid.cpp
NativeConfig.cpp
WiiUtils.cpp
)

target_link_libraries(main
Expand Down
9 changes: 0 additions & 9 deletions Source/Android/jni/MainAndroid.cpp
Expand Up @@ -45,7 +45,6 @@
#include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/Profiler.h"
#include "Core/State.h"
#include "Core/WiiUtils.h"

#include "DiscIO/Blob.h"
#include "DiscIO/Enums.h"
Expand Down Expand Up @@ -596,14 +595,6 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ReloadLogger
Common::Log::LogManager::Init();
}

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_InstallWAD(JNIEnv* env,
jclass,
jstring jFile)
{
const std::string path = GetJString(env, jFile);
return static_cast<jboolean>(WiiUtils::InstallWAD(path));
}

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ConvertDiscImage(
JNIEnv* env, jclass, jstring jInPath, jstring jOutPath, jint jPlatform, jint jFormat,
jint jBlockSize, jint jCompression, jint jCompressionLevel, jboolean jScrub, jobject jCallback)
Expand Down
59 changes: 59 additions & 0 deletions Source/Android/jni/WiiUtils.cpp
@@ -0,0 +1,59 @@
// Copyright 2021 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include <string>

#include <jni.h>

#include "jni/AndroidCommon/AndroidCommon.h"
#include "jni/AndroidCommon/IDCache.h"

#include "Core/HW/WiiSave.h"
#include "Core/WiiUtils.h"

// The hardcoded values here must match WiiUtils.java
static jint ConvertCopyResult(WiiSave::CopyResult result)
{
switch (result)
{
case WiiSave::CopyResult::Success:
return 0;
case WiiSave::CopyResult::Error:
return 1;
case WiiSave::CopyResult::Cancelled:
return 2;
case WiiSave::CopyResult::CorruptedSource:
return 3;
case WiiSave::CopyResult::TitleMissing:
return 4;
default:
ASSERT(false);
return 1;
}

static_assert(static_cast<int>(WiiSave::CopyResult::NumberOfEntries) == 5);
}

extern "C" {

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_utils_WiiUtils_installWAD(JNIEnv* env,
jclass,
jstring jFile)
{
const std::string path = GetJString(env, jFile);
return static_cast<jboolean>(WiiUtils::InstallWAD(path));
}

JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_utils_WiiUtils_importWiiSave(
JNIEnv* env, jclass, jstring jFile, jobject jCanOverwrite)
{
const std::string path = GetJString(env, jFile);
const auto can_overwrite = [&] {
const jmethodID get = IDCache::GetBooleanSupplierGet();
return static_cast<bool>(env->CallBooleanMethod(jCanOverwrite, get));
};

return ConvertCopyResult(WiiSave::Import(path, can_overwrite));
}
}
1 change: 1 addition & 0 deletions Source/Core/Core/HW/WiiSave.h
Expand Up @@ -39,6 +39,7 @@ enum class CopyResult
Cancelled,
CorruptedSource,
TitleMissing,
NumberOfEntries
};

CopyResult Copy(Storage* source, Storage* destination);
Expand Down