2014-12-04 07:56:54 +00:00
|
|
|
#include <jni.h>
|
2014-12-07 03:05:14 +00:00
|
|
|
#include <cassert>
|
2015-03-11 01:03:38 -04:00
|
|
|
#include <android/native_window.h>
|
|
|
|
#include <android/native_window_jni.h>
|
2016-05-23 13:30:46 -04:00
|
|
|
#include "android/AssetManager.h"
|
2021-08-13 17:21:17 -04:00
|
|
|
#include "android/ContentResolver.h"
|
2017-11-11 11:55:09 -05:00
|
|
|
#include "android/JavaVM.h"
|
2021-08-25 13:44:26 -04:00
|
|
|
#include "android/android_database_Cursor.h"
|
2021-08-13 17:21:17 -04:00
|
|
|
#include "android/android_net_Uri.h"
|
|
|
|
#include "android/android_os_ParcelFileDescriptor.h"
|
2021-08-04 09:35:56 -04:00
|
|
|
#include "android/java_security_MessageDigest.h"
|
|
|
|
#include "android/javax_crypto_Mac.h"
|
|
|
|
#include "android/javax_crypto_spec_SecretKeySpec.h"
|
2014-12-07 03:05:14 +00:00
|
|
|
#include "PathUtils.h"
|
2015-04-24 01:51:40 -04:00
|
|
|
#include "../AppConfig.h"
|
2015-07-23 23:34:37 -04:00
|
|
|
#include "../DiskUtils.h"
|
2015-10-31 21:07:01 -04:00
|
|
|
#include "../PH_Generic.h"
|
2014-12-04 07:56:54 +00:00
|
|
|
#include "../PS2VM.h"
|
2015-04-24 01:51:40 -04:00
|
|
|
#include "../PS2VM_Preferences.h"
|
2015-05-06 03:18:38 -04:00
|
|
|
#include "../gs/GSH_Null.h"
|
2015-07-08 23:15:06 -04:00
|
|
|
#include "NativeShared.h"
|
2015-03-11 01:03:38 -04:00
|
|
|
#include "GSH_OpenGLAndroid.h"
|
2021-06-26 08:37:31 -04:00
|
|
|
#include "GSH_VulkanAndroid.h"
|
2016-04-01 21:55:08 -04:00
|
|
|
#include "SH_OpenSL.h"
|
2019-08-01 12:42:47 -04:00
|
|
|
#include "ui_shared/StatsManager.h"
|
2017-11-13 16:25:34 -05:00
|
|
|
#include "com_virtualapplications_play_Bootable.h"
|
2017-11-27 13:09:40 -05:00
|
|
|
#include "http/java_io_InputStream.h"
|
|
|
|
#include "http/java_io_OutputStream.h"
|
|
|
|
#include "http/java_net_HttpURLConnection.h"
|
|
|
|
#include "http/java_net_URL.h"
|
2014-12-04 07:56:54 +00:00
|
|
|
|
2015-06-30 05:26:01 -04:00
|
|
|
CPS2VM* g_virtualMachine = nullptr;
|
2019-08-16 17:11:35 -04:00
|
|
|
CPS2VM::ProfileFrameDoneSignal::Connection g_ProfileFrameDoneConnection;
|
|
|
|
Framework::CSignal<void(uint32)>::Connection g_OnNewFrameConnection;
|
2021-09-28 15:02:53 -04:00
|
|
|
int g_currentGsHandlerId = -1;
|
2014-12-07 03:05:14 +00:00
|
|
|
|
2021-09-28 15:02:53 -04:00
|
|
|
#define PREF_VIDEO_GS_HANDLER ("video.gshandler")
|
2016-04-01 21:55:08 -04:00
|
|
|
#define PREF_AUDIO_ENABLEOUTPUT ("audio.enableoutput")
|
|
|
|
|
2021-09-28 15:02:53 -04:00
|
|
|
#define PREFERENCE_VALUE_VIDEO_GS_HANDLER_OPENGL 0
|
|
|
|
#define PREFERENCE_VALUE_VIDEO_GS_HANDLER_VULKAN 1
|
|
|
|
|
2016-04-01 21:55:08 -04:00
|
|
|
static void SetupSoundHandler()
|
|
|
|
{
|
|
|
|
assert(g_virtualMachine != nullptr);
|
|
|
|
auto audioEnabled = CAppConfig::GetInstance().GetPreferenceBoolean(PREF_AUDIO_ENABLEOUTPUT);
|
|
|
|
if(audioEnabled)
|
|
|
|
{
|
|
|
|
g_virtualMachine->CreateSoundHandler(&CSH_OpenSL::HandlerFactory);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_virtualMachine->DestroySoundHandler();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-05 00:18:31 -04:00
|
|
|
static void ResetVirtualMachine()
|
|
|
|
{
|
|
|
|
assert(g_virtualMachine != nullptr);
|
|
|
|
g_virtualMachine->Pause();
|
|
|
|
g_virtualMachine->Reset();
|
2019-10-12 10:58:54 +01:00
|
|
|
g_virtualMachine->ReloadSpuBlockCount();
|
2017-06-05 00:18:31 -04:00
|
|
|
SetupSoundHandler();
|
|
|
|
}
|
|
|
|
|
2017-11-11 11:55:09 -05:00
|
|
|
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* aReserved)
|
|
|
|
{
|
|
|
|
Framework::CJavaVM::SetJavaVM(vm);
|
2017-11-27 13:09:40 -05:00
|
|
|
java::net::URL_ClassInfo::GetInstance().PrepareClassInfo();
|
|
|
|
java::net::HttpURLConnection_ClassInfo::GetInstance().PrepareClassInfo();
|
|
|
|
java::io::InputStream_ClassInfo::GetInstance().PrepareClassInfo();
|
|
|
|
java::io::OutputStream_ClassInfo::GetInstance().PrepareClassInfo();
|
2021-08-04 09:35:56 -04:00
|
|
|
java::security::MessageDigest_ClassInfo::GetInstance().PrepareClassInfo();
|
|
|
|
javax::crypto::Mac_ClassInfo::GetInstance().PrepareClassInfo();
|
|
|
|
javax::crypto::spec::SecretKeySpec_ClassInfo::GetInstance().PrepareClassInfo();
|
2021-08-13 17:21:17 -04:00
|
|
|
android::content::ContentResolver_ClassInfo::GetInstance().PrepareClassInfo();
|
2021-08-25 13:44:26 -04:00
|
|
|
android::database::Cursor_ClassInfo::GetInstance().PrepareClassInfo();
|
2021-08-13 17:21:17 -04:00
|
|
|
android::net::Uri_ClassInfo::GetInstance().PrepareClassInfo();
|
|
|
|
android::os::ParcelFileDescriptor_ClassInfo::GetInstance().PrepareClassInfo();
|
2017-11-13 16:25:34 -05:00
|
|
|
com::virtualapplications::play::Bootable_ClassInfo::GetInstance().PrepareClassInfo();
|
2017-11-11 11:55:09 -05:00
|
|
|
return JNI_VERSION_1_6;
|
|
|
|
}
|
|
|
|
|
2014-12-07 03:05:14 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_setFilesDirPath(JNIEnv* env, jobject obj, jstring dirPathString)
|
|
|
|
{
|
|
|
|
auto dirPath = env->GetStringUTFChars(dirPathString, 0);
|
|
|
|
Framework::PathUtils::SetFilesDirPath(dirPath);
|
|
|
|
env->ReleaseStringUTFChars(dirPathString, dirPath);
|
|
|
|
}
|
|
|
|
|
2021-08-04 09:35:56 -04:00
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_setCacheDirPath(JNIEnv* env, jobject obj, jstring dirPathString)
|
|
|
|
{
|
|
|
|
auto dirPath = env->GetStringUTFChars(dirPathString, 0);
|
|
|
|
Framework::PathUtils::SetCacheDirPath(dirPath);
|
|
|
|
env->ReleaseStringUTFChars(dirPathString, dirPath);
|
|
|
|
}
|
|
|
|
|
2016-05-23 13:30:46 -04:00
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_setAssetManager(JNIEnv* env, jobject obj, jobject assetManagerJava)
|
|
|
|
{
|
|
|
|
auto assetManager = AAssetManager_fromJava(env, assetManagerJava);
|
|
|
|
assert(assetManager != nullptr);
|
|
|
|
Framework::Android::CAssetManager::GetInstance().SetAssetManager(assetManager);
|
|
|
|
}
|
|
|
|
|
2021-08-13 17:21:17 -04:00
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_setContentResolver(JNIEnv* env, jclass clazz, jobject contentResolverJava)
|
|
|
|
{
|
|
|
|
auto contentResolver = Framework::CJavaObject::CastTo<android::content::ContentResolver>(contentResolverJava);
|
|
|
|
Framework::Android::CContentResolver::GetInstance().SetContentResolver(std::move(contentResolver));
|
|
|
|
}
|
|
|
|
|
2014-12-07 03:05:14 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_createVirtualMachine(JNIEnv* env, jobject obj)
|
|
|
|
{
|
2015-04-05 23:29:49 -04:00
|
|
|
assert(g_virtualMachine == nullptr);
|
2014-12-07 03:05:14 +00:00
|
|
|
g_virtualMachine = new CPS2VM();
|
|
|
|
g_virtualMachine->Initialize();
|
2015-10-31 21:07:01 -04:00
|
|
|
g_virtualMachine->CreatePadHandler(CPH_Generic::GetFactoryFunction());
|
2015-09-06 21:33:17 +01:00
|
|
|
#ifdef PROFILE
|
2019-07-01 13:11:23 +01:00
|
|
|
g_ProfileFrameDoneConnection = g_virtualMachine->ProfileFrameDone.Connect(std::bind(&CStatsManager::OnProfileFrameDone, &CStatsManager::GetInstance(), g_virtualMachine, std::placeholders::_1));
|
2015-09-06 21:33:17 +01:00
|
|
|
#endif
|
2021-09-28 15:02:53 -04:00
|
|
|
CAppConfig::GetInstance().RegisterPreferenceInteger(PREF_VIDEO_GS_HANDLER, PREFERENCE_VALUE_VIDEO_GS_HANDLER_OPENGL);
|
2016-04-01 21:55:08 -04:00
|
|
|
CAppConfig::GetInstance().RegisterPreferenceBoolean(PREF_AUDIO_ENABLEOUTPUT, true);
|
2016-01-18 19:54:34 -05:00
|
|
|
CGSH_OpenGL::RegisterPreferences();
|
2021-09-28 15:02:53 -04:00
|
|
|
g_currentGsHandlerId = -1;
|
2014-12-07 03:05:14 +00:00
|
|
|
}
|
|
|
|
|
2015-04-05 23:29:49 -04:00
|
|
|
extern "C" JNIEXPORT jboolean JNICALL Java_com_virtualapplications_play_NativeInterop_isVirtualMachineCreated(JNIEnv* env, jobject obj)
|
2014-12-04 07:56:54 +00:00
|
|
|
{
|
2015-04-05 23:29:49 -04:00
|
|
|
return (g_virtualMachine != nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_resumeVirtualMachine(JNIEnv* env, jobject obj)
|
|
|
|
{
|
|
|
|
assert(g_virtualMachine != nullptr);
|
|
|
|
if(g_virtualMachine == nullptr) return;
|
|
|
|
g_virtualMachine->Resume();
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_pauseVirtualMachine(JNIEnv* env, jobject obj)
|
|
|
|
{
|
|
|
|
assert(g_virtualMachine != nullptr);
|
|
|
|
if(g_virtualMachine == nullptr) return;
|
|
|
|
g_virtualMachine->Pause();
|
|
|
|
}
|
|
|
|
|
2015-08-24 22:37:21 -04:00
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_loadState(JNIEnv* env, jobject obj, jint slot)
|
|
|
|
{
|
|
|
|
assert(g_virtualMachine != nullptr);
|
|
|
|
if(g_virtualMachine == nullptr) return;
|
2017-09-07 18:00:30 -04:00
|
|
|
auto stateFilePath = g_virtualMachine->GenerateStatePath(slot);
|
2017-09-07 15:45:28 -04:00
|
|
|
auto resultFuture = g_virtualMachine->LoadState(stateFilePath);
|
|
|
|
if(!resultFuture.get())
|
2015-08-24 22:37:21 -04:00
|
|
|
{
|
|
|
|
jclass exceptionClass = env->FindClass("java/lang/Exception");
|
|
|
|
env->ThrowNew(exceptionClass, "LoadState failed.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_saveState(JNIEnv* env, jobject obj, jint slot)
|
|
|
|
{
|
|
|
|
assert(g_virtualMachine != nullptr);
|
|
|
|
if(g_virtualMachine == nullptr) return;
|
2017-09-07 18:00:30 -04:00
|
|
|
auto stateFilePath = g_virtualMachine->GenerateStatePath(slot);
|
2017-09-07 15:45:28 -04:00
|
|
|
auto resultFuture = g_virtualMachine->SaveState(stateFilePath);
|
|
|
|
if(!resultFuture.get())
|
2015-08-24 22:37:21 -04:00
|
|
|
{
|
|
|
|
jclass exceptionClass = env->FindClass("java/lang/Exception");
|
|
|
|
env->ThrowNew(exceptionClass, "SaveState failed.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-05 23:29:49 -04:00
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_loadElf(JNIEnv* env, jobject obj, jstring selectedFilePath)
|
|
|
|
{
|
|
|
|
assert(g_virtualMachine != nullptr);
|
2017-06-05 00:18:31 -04:00
|
|
|
ResetVirtualMachine();
|
2015-04-24 01:52:36 -04:00
|
|
|
try
|
|
|
|
{
|
2017-12-02 12:59:32 -05:00
|
|
|
g_virtualMachine->m_ee->m_os->BootFromFile(GetStringFromJstring(env, selectedFilePath));
|
2015-04-24 01:52:36 -04:00
|
|
|
}
|
|
|
|
catch(const std::exception& exception)
|
|
|
|
{
|
|
|
|
jclass exceptionClass = env->FindClass("java/lang/Exception");
|
|
|
|
env->ThrowNew(exceptionClass, exception.what());
|
|
|
|
}
|
2015-04-05 23:29:49 -04:00
|
|
|
}
|
|
|
|
|
2015-04-24 01:51:40 -04:00
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_bootDiskImage(JNIEnv* env, jobject obj, jstring selectedFilePath)
|
|
|
|
{
|
|
|
|
assert(g_virtualMachine != nullptr);
|
2018-01-15 14:14:59 -05:00
|
|
|
CAppConfig::GetInstance().SetPreferencePath(PREF_PS2_CDROM0_PATH, GetStringFromJstring(env, selectedFilePath));
|
2017-06-05 00:18:31 -04:00
|
|
|
ResetVirtualMachine();
|
2015-04-24 01:51:40 -04:00
|
|
|
try
|
|
|
|
{
|
2015-12-05 23:28:12 -05:00
|
|
|
g_virtualMachine->m_ee->m_os->BootFromCDROM();
|
2015-04-24 01:51:40 -04:00
|
|
|
}
|
|
|
|
catch(const std::exception& exception)
|
|
|
|
{
|
|
|
|
jclass exceptionClass = env->FindClass("java/lang/Exception");
|
|
|
|
env->ThrowNew(exceptionClass, exception.what());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-05 23:29:49 -04:00
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_setupGsHandler(JNIEnv* env, jobject obj, jobject surface)
|
|
|
|
{
|
|
|
|
auto nativeWindow = ANativeWindow_fromSurface(env, surface);
|
2015-04-06 02:34:34 -04:00
|
|
|
auto gsHandler = g_virtualMachine->GetGSHandler();
|
2021-09-28 15:02:53 -04:00
|
|
|
int gsHandlerId = CAppConfig::GetInstance().GetPreferenceInteger(PREF_VIDEO_GS_HANDLER);
|
|
|
|
bool recreateNeeded = (gsHandler == nullptr) || (g_currentGsHandlerId != gsHandlerId);
|
|
|
|
if(recreateNeeded)
|
2015-04-06 02:34:34 -04:00
|
|
|
{
|
2021-09-28 15:02:53 -04:00
|
|
|
switch(gsHandlerId)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case PREFERENCE_VALUE_VIDEO_GS_HANDLER_OPENGL:
|
|
|
|
g_virtualMachine->CreateGSHandler(CGSH_OpenGLAndroid::GetFactoryFunction(nativeWindow));
|
|
|
|
break;
|
|
|
|
case PREFERENCE_VALUE_VIDEO_GS_HANDLER_VULKAN:
|
|
|
|
g_virtualMachine->CreateGSHandler(CGSH_VulkanAndroid::GetFactoryFunction(nativeWindow));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
g_currentGsHandlerId = gsHandlerId;
|
2019-07-01 13:11:23 +01:00
|
|
|
g_OnNewFrameConnection = g_virtualMachine->m_ee->m_gs->OnNewFrame.Connect(
|
2019-06-04 00:27:37 +01:00
|
|
|
std::bind(&CStatsManager::OnNewFrame, &CStatsManager::GetInstance(), std::placeholders::_1));
|
2015-04-06 02:34:34 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-09-28 14:02:27 -04:00
|
|
|
if(auto windowUpdateListener = dynamic_cast<INativeWindowUpdateListener*>(gsHandler))
|
|
|
|
{
|
|
|
|
windowUpdateListener->SetWindow(nativeWindow);
|
|
|
|
}
|
2015-04-06 02:34:34 -04:00
|
|
|
}
|
2014-12-04 07:56:54 +00:00
|
|
|
}
|
2021-06-17 15:13:20 -04:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT void JNICALL Java_com_virtualapplications_play_NativeInterop_notifyPreferencesChanged(JNIEnv* env, jobject obj)
|
|
|
|
{
|
2021-06-17 15:57:40 -04:00
|
|
|
SetupSoundHandler();
|
|
|
|
g_virtualMachine->ReloadSpuBlockCount();
|
2021-06-17 15:13:20 -04:00
|
|
|
auto gsHandler = g_virtualMachine->GetGSHandler();
|
|
|
|
if(gsHandler != nullptr)
|
|
|
|
{
|
|
|
|
gsHandler->NotifyPreferencesChanged();
|
|
|
|
}
|
|
|
|
}
|