Merge pull request #8902 from JosJuice/android-convert

Android: Add disc image conversion
This commit is contained in:
JMC47
2020-09-23 12:27:43 -04:00
committed by GitHub
37 changed files with 1366 additions and 140 deletions

View File

@ -11,6 +11,7 @@
#include <jni.h>
#include "Common/StringUtil.h"
#include "jni/AndroidCommon/IDCache.h"
std::string GetJString(JNIEnv* env, jstring jstr)
{
@ -40,3 +41,27 @@ std::vector<std::string> JStringArrayToVector(JNIEnv* env, jobjectArray array)
return result;
}
int OpenAndroidContent(const std::string& uri, const std::string& mode)
{
JNIEnv* env = IDCache::GetEnvForThread();
const jint fd = env->CallStaticIntMethod(IDCache::GetContentHandlerClass(),
IDCache::GetContentHandlerOpenFd(), ToJString(env, uri),
ToJString(env, mode));
// We can get an IllegalArgumentException when passing an invalid mode
if (env->ExceptionCheck())
{
env->ExceptionDescribe();
abort();
}
return fd;
}
bool DeleteAndroidContent(const std::string& uri)
{
JNIEnv* env = IDCache::GetEnvForThread();
return env->CallStaticBooleanMethod(IDCache::GetContentHandlerClass(),
IDCache::GetContentHandlerDelete(), ToJString(env, uri));
}

View File

@ -11,3 +11,6 @@
std::string GetJString(JNIEnv* env, jstring jstr);
jstring ToJString(JNIEnv* env, const std::string& str);
std::vector<std::string> JStringArrayToVector(JNIEnv* env, jobjectArray array);
int OpenAndroidContent(const std::string& uri, const std::string& mode);
bool DeleteAndroidContent(const std::string& uri);

View File

@ -0,0 +1,15 @@
add_library(androidcommon STATIC
AndroidCommon.cpp
AndroidCommon.h
IDCache.cpp
IDCache.h
)
target_link_libraries(androidcommon
PRIVATE
android
log
"-Wl,--no-warn-mismatch"
"-Wl,--whole-archive"
"-Wl,--no-whole-archive"
)

View File

@ -36,6 +36,13 @@ static jclass s_ini_file_section_class;
static jfieldID s_ini_file_section_pointer;
static jmethodID s_ini_file_section_constructor;
static jclass s_compress_cb_class;
static jmethodID s_compress_cb_run;
static jclass s_content_handler_class;
static jmethodID s_content_handler_open_fd;
static jmethodID s_content_handler_delete;
namespace IDCache
{
JNIEnv* GetEnvForThread()
@ -161,6 +168,31 @@ jmethodID GetIniFileSectionConstructor()
return s_ini_file_section_constructor;
}
jclass GetCompressCallbackClass()
{
return s_compress_cb_class;
}
jmethodID GetCompressCallbackRun()
{
return s_compress_cb_run;
}
jclass GetContentHandlerClass()
{
return s_content_handler_class;
}
jmethodID GetContentHandlerOpenFd()
{
return s_content_handler_open_fd;
}
jmethodID GetContentHandlerDelete()
{
return s_content_handler_delete;
}
} // namespace IDCache
#ifdef __cplusplus
@ -223,6 +255,19 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
s_linked_hash_map_put = env->GetMethodID(
s_linked_hash_map_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
const jclass compress_cb_class =
env->FindClass("org/dolphinemu/dolphinemu/utils/CompressCallback");
s_compress_cb_class = reinterpret_cast<jclass>(env->NewGlobalRef(compress_cb_class));
s_compress_cb_run = env->GetMethodID(s_compress_cb_class, "run", "(Ljava/lang/String;F)Z");
const jclass content_handler_class =
env->FindClass("org/dolphinemu/dolphinemu/utils/ContentHandler");
s_content_handler_class = reinterpret_cast<jclass>(env->NewGlobalRef(content_handler_class));
s_content_handler_open_fd = env->GetStaticMethodID(s_content_handler_class, "openFd",
"(Ljava/lang/String;Ljava/lang/String;)I");
s_content_handler_delete =
env->GetStaticMethodID(s_content_handler_class, "delete", "(Ljava/lang/String;)Z");
return JNI_VERSION;
}
@ -239,6 +284,8 @@ void JNI_OnUnload(JavaVM* vm, void* reserved)
env->DeleteGlobalRef(s_linked_hash_map_class);
env->DeleteGlobalRef(s_ini_file_class);
env->DeleteGlobalRef(s_ini_file_section_class);
env->DeleteGlobalRef(s_compress_cb_class);
env->DeleteGlobalRef(s_content_handler_class);
}
#ifdef __cplusplus

View File

@ -38,4 +38,11 @@ jclass GetIniFileSectionClass();
jfieldID GetIniFileSectionPointer();
jmethodID GetIniFileSectionConstructor();
jclass GetCompressCallbackClass();
jmethodID GetCompressCallbackRun();
jclass GetContentHandlerClass();
jmethodID GetContentHandlerOpenFd();
jmethodID GetContentHandlerDelete();
} // namespace IDCache

View File

@ -1,7 +1,6 @@
add_library(main SHARED
AndroidCommon/AndroidCommon.cpp
AndroidCommon/IDCache.cpp
GameList/GameFile.cpp
GameList/GameFile.h
GameList/GameFileCache.cpp
IniFile.cpp
MainAndroid.cpp
@ -10,6 +9,7 @@ add_library(main SHARED
target_link_libraries(main
PRIVATE
androidcommon
core
uicommon
)
@ -32,3 +32,5 @@ file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/Source/Android/app/src/main/assets/Sys/R
file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/Source/Android/app/src/main/assets/Sys/Themes/)
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} main)
add_subdirectory(AndroidCommon)

View File

@ -63,6 +63,8 @@ JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getDiscNumb
jobject obj);
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getRevision(JNIEnv* env,
jobject obj);
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBlobType(JNIEnv* env,
jobject obj);
JNIEXPORT jstring JNICALL
Java_org_dolphinemu_dolphinemu_model_GameFile_getBlobTypeString(JNIEnv* env, jobject obj);
JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBlockSize(JNIEnv* env,
@ -71,8 +73,12 @@ JNIEXPORT jstring JNICALL
Java_org_dolphinemu_dolphinemu_model_GameFile_getCompressionMethod(JNIEnv* env, jobject obj);
JNIEXPORT jboolean JNICALL
Java_org_dolphinemu_dolphinemu_model_GameFile_shouldShowFileFormatDetails(JNIEnv* env, jobject obj);
JNIEXPORT jboolean JNICALL
Java_org_dolphinemu_dolphinemu_model_GameFile_shouldAllowConversion(JNIEnv* env, jobject obj);
JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getFileSize(JNIEnv* env,
jobject obj);
JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_isDatelDisc(JNIEnv* env,
jobject obj);
JNIEXPORT jintArray JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBanner(JNIEnv* env,
jobject obj);
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBannerWidth(JNIEnv* env,
@ -154,6 +160,12 @@ JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getRevision
return GetRef(env, obj)->GetRevision();
}
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBlobType(JNIEnv* env,
jobject obj)
{
return static_cast<jint>(GetRef(env, obj)->GetBlobType());
}
JNIEXPORT jstring JNICALL
Java_org_dolphinemu_dolphinemu_model_GameFile_getBlobTypeString(JNIEnv* env, jobject obj)
{
@ -175,7 +187,13 @@ Java_org_dolphinemu_dolphinemu_model_GameFile_getCompressionMethod(JNIEnv* env,
JNIEXPORT jboolean JNICALL
Java_org_dolphinemu_dolphinemu_model_GameFile_shouldShowFileFormatDetails(JNIEnv* env, jobject obj)
{
return GetRef(env, obj)->ShouldShowFileFormatDetails();
return static_cast<jboolean>(GetRef(env, obj)->ShouldShowFileFormatDetails());
}
JNIEXPORT jboolean JNICALL
Java_org_dolphinemu_dolphinemu_model_GameFile_shouldAllowConversion(JNIEnv* env, jobject obj)
{
return static_cast<jboolean>(GetRef(env, obj)->ShouldAllowConversion());
}
JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getFileSize(JNIEnv* env,
@ -184,6 +202,12 @@ JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getFileSiz
return GetRef(env, obj)->GetFileSize();
}
JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_isDatelDisc(JNIEnv* env,
jobject obj)
{
return static_cast<jboolean>(GetRef(env, obj)->IsDatelDisc());
}
JNIEXPORT jintArray JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getBanner(JNIEnv* env,
jobject obj)
{

View File

@ -18,6 +18,7 @@
#include <utility>
#include "Common/AndroidAnalytics.h"
#include "Common/Assert.h"
#include "Common/CPUDetect.h"
#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
@ -26,6 +27,7 @@
#include "Common/IniFile.h"
#include "Common/Logging/LogManager.h"
#include "Common/MsgHandler.h"
#include "Common/ScopeGuard.h"
#include "Common/Version.h"
#include "Common/WindowSystemInfo.h"
@ -45,7 +47,9 @@
#include "Core/State.h"
#include "Core/WiiUtils.h"
#include "DiscIO/Blob.h"
#include "DiscIO/Enums.h"
#include "DiscIO/ScrubbedBlob.h"
#include "DiscIO/Volume.h"
#include "InputCommon/ControllerInterface/Android/Android.h"
@ -663,6 +667,65 @@ JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_InstallW
return static_cast<jboolean>(WiiUtils::InstallWAD(path));
}
JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ConvertDiscImage(
JNIEnv* env, jobject obj, jstring jInPath, jstring jOutPath, jint jPlatform, jint jFormat,
jint jBlockSize, jint jCompression, jint jCompressionLevel, jboolean jScrub, jobject jCallback)
{
const std::string in_path = GetJString(env, jInPath);
const std::string out_path = GetJString(env, jOutPath);
const DiscIO::Platform platform = static_cast<DiscIO::Platform>(jPlatform);
const DiscIO::BlobType format = static_cast<DiscIO::BlobType>(jFormat);
const DiscIO::WIARVZCompressionType compression =
static_cast<DiscIO::WIARVZCompressionType>(jCompression);
const bool scrub = static_cast<bool>(jScrub);
std::unique_ptr<DiscIO::BlobReader> blob_reader;
if (scrub)
blob_reader = DiscIO::ScrubbedBlob::Create(in_path);
else
blob_reader = DiscIO::CreateBlobReader(in_path);
if (!blob_reader)
return static_cast<jboolean>(false);
jobject jCallbackGlobal = env->NewGlobalRef(jCallback);
Common::ScopeGuard scope_guard([jCallbackGlobal, env] { env->DeleteGlobalRef(jCallbackGlobal); });
const auto callback = [&jCallbackGlobal](const std::string& text, float completion) {
JNIEnv* env = IDCache::GetEnvForThread();
return static_cast<bool>(env->CallBooleanMethod(
jCallbackGlobal, IDCache::GetCompressCallbackRun(), ToJString(env, text), completion));
};
bool success = false;
switch (format)
{
case DiscIO::BlobType::PLAIN:
success = DiscIO::ConvertToPlain(blob_reader.get(), in_path, out_path, callback);
break;
case DiscIO::BlobType::GCZ:
success =
DiscIO::ConvertToGCZ(blob_reader.get(), in_path, out_path,
platform == DiscIO::Platform::WiiDisc ? 1 : 0, jBlockSize, callback);
break;
case DiscIO::BlobType::WIA:
case DiscIO::BlobType::RVZ:
success = DiscIO::ConvertToWIAOrRVZ(blob_reader.get(), in_path, out_path,
format == DiscIO::BlobType::RVZ, compression,
jCompressionLevel, jBlockSize, callback);
break;
default:
ASSERT(false);
break;
}
return static_cast<jboolean>(success);
}
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_FormatSize(JNIEnv* env,
jobject obj,
jlong bytes,