android: Minimal JNI for yuzu.
This commit is contained in:
		| @@ -195,3 +195,8 @@ endif() | ||||
| if (ENABLE_WEB_SERVICE) | ||||
|     add_subdirectory(web_service) | ||||
| endif() | ||||
|  | ||||
| if (ANDROID) | ||||
|     add_subdirectory(android/app/src/main/jni) | ||||
|     target_include_directories(yuzu-android PRIVATE android/app/src/main) | ||||
| endif() | ||||
|   | ||||
							
								
								
									
										15
									
								
								src/android/app/src/main/jni/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/android/app/src/main/jni/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| add_library(yuzu-android SHARED | ||||
|     emu_window/emu_window.cpp | ||||
|     emu_window/emu_window.h | ||||
|     id_cache.cpp | ||||
|     id_cache.h | ||||
|     native.cpp | ||||
|     native.h | ||||
| ) | ||||
|  | ||||
| set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) | ||||
|  | ||||
| target_link_libraries(yuzu-android PRIVATE audio_core common core input_common) | ||||
| target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad inih jnigraphics log) | ||||
|  | ||||
| set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} yuzu-android) | ||||
							
								
								
									
										58
									
								
								src/android/app/src/main/jni/emu_window/emu_window.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/android/app/src/main/jni/emu_window/emu_window.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| #include <android/native_window_jni.h> | ||||
|  | ||||
| #include "common/logging/log.h" | ||||
| #include "input_common/drivers/touch_screen.h" | ||||
| #include "input_common/drivers/virtual_gamepad.h" | ||||
| #include "input_common/main.h" | ||||
| #include "jni/emu_window/emu_window.h" | ||||
|  | ||||
| void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { | ||||
|     render_window = surface; | ||||
| } | ||||
|  | ||||
| bool EmuWindow_Android::OnTouchEvent(float x, float y, bool pressed) { | ||||
|     if (pressed) { | ||||
|         input_subsystem->GetTouchScreen()->TouchPressed(NormalizeX(x), NormalizeY(y), 0); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     input_subsystem->GetTouchScreen()->ReleaseAllTouch(); | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| void EmuWindow_Android::OnTouchMoved(float x, float y) { | ||||
|     input_subsystem->GetTouchScreen()->TouchMoved(NormalizeX(x), NormalizeY(y), 0); | ||||
| } | ||||
|  | ||||
| void EmuWindow_Android::OnGamepadEvent(int button_id, bool pressed) { | ||||
|     input_subsystem->GetVirtualGamepad()->SetButtonState(0, button_id, pressed); | ||||
| } | ||||
|  | ||||
| void EmuWindow_Android::OnGamepadMoveEvent(float x, float y) { | ||||
|     input_subsystem->GetVirtualGamepad()->SetStickPosition( | ||||
|         0, InputCommon::VirtualGamepad::VirtualStick::Left, x, y); | ||||
| } | ||||
|  | ||||
| EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_, | ||||
|                                      ANativeWindow* surface_) | ||||
|     : input_subsystem{input_subsystem_} { | ||||
|     LOG_INFO(Frontend, "initializing"); | ||||
|  | ||||
|     if (!surface_) { | ||||
|         LOG_CRITICAL(Frontend, "surface is nullptr"); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     window_width = ANativeWindow_getWidth(surface_); | ||||
|     window_height = ANativeWindow_getHeight(surface_); | ||||
|  | ||||
|     host_window = surface_; | ||||
|     window_info.type = Core::Frontend::WindowSystemType::Android; | ||||
|     window_info.render_surface = reinterpret_cast<void*>(host_window); | ||||
|  | ||||
|     input_subsystem->Initialize(); | ||||
| } | ||||
|  | ||||
| EmuWindow_Android::~EmuWindow_Android() { | ||||
|     input_subsystem->Shutdown(); | ||||
| } | ||||
							
								
								
									
										51
									
								
								src/android/app/src/main/jni/emu_window/emu_window.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/android/app/src/main/jni/emu_window/emu_window.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "core/frontend/emu_window.h" | ||||
| #include "input_common/main.h" | ||||
|  | ||||
| struct ANativeWindow; | ||||
|  | ||||
| class SharedContext_Android : public Core::Frontend::GraphicsContext { | ||||
| public: | ||||
|     SharedContext_Android() = default; | ||||
|     ~SharedContext_Android() = default; | ||||
|     void MakeCurrent() override {} | ||||
|     void DoneCurrent() override {} | ||||
| }; | ||||
|  | ||||
| class EmuWindow_Android : public Core::Frontend::EmuWindow { | ||||
| public: | ||||
|     EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_, ANativeWindow* surface_); | ||||
|     ~EmuWindow_Android(); | ||||
|  | ||||
|     void OnSurfaceChanged(ANativeWindow* surface); | ||||
|     bool OnTouchEvent(float x, float y, bool pressed); | ||||
|     void OnTouchMoved(float x, float y); | ||||
|     void OnGamepadEvent(int button, bool pressed); | ||||
|     void OnGamepadMoveEvent(float x, float y); | ||||
|     void OnFrameDisplayed() override {} | ||||
|  | ||||
|     std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override { | ||||
|         return {std::make_unique<SharedContext_Android>()}; | ||||
|     } | ||||
|     bool IsShown() const override { | ||||
|         return true; | ||||
|     }; | ||||
|  | ||||
| private: | ||||
|     float NormalizeX(float x) const { | ||||
|         return std::clamp(x / window_width, 0.f, 1.f); | ||||
|     } | ||||
|  | ||||
|     float NormalizeY(float y) const { | ||||
|         return std::clamp(y / window_height, 0.f, 1.f); | ||||
|     } | ||||
|  | ||||
|     InputCommon::InputSubsystem* input_subsystem{}; | ||||
|  | ||||
|     ANativeWindow* render_window{}; | ||||
|     ANativeWindow* host_window{}; | ||||
|  | ||||
|     float window_width{}; | ||||
|     float window_height{}; | ||||
| }; | ||||
							
								
								
									
										36
									
								
								src/android/app/src/main/jni/id_cache.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/android/app/src/main/jni/id_cache.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| #include "jni/id_cache.h" | ||||
|  | ||||
| static JavaVM* s_java_vm; | ||||
| static jclass s_native_library_class; | ||||
| static jmethodID s_exit_emulation_activity; | ||||
|  | ||||
| namespace IDCache { | ||||
|  | ||||
| JNIEnv* GetEnvForThread() { | ||||
|     thread_local static struct OwnedEnv { | ||||
|         OwnedEnv() { | ||||
|             status = s_java_vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); | ||||
|             if (status == JNI_EDETACHED) | ||||
|                 s_java_vm->AttachCurrentThread(&env, nullptr); | ||||
|         } | ||||
|  | ||||
|         ~OwnedEnv() { | ||||
|             if (status == JNI_EDETACHED) | ||||
|                 s_java_vm->DetachCurrentThread(); | ||||
|         } | ||||
|  | ||||
|         int status; | ||||
|         JNIEnv* env = nullptr; | ||||
|     } owned; | ||||
|     return owned.env; | ||||
| } | ||||
|  | ||||
| jclass GetNativeLibraryClass() { | ||||
|     return s_native_library_class; | ||||
| } | ||||
|  | ||||
| jmethodID GetExitEmulationActivity() { | ||||
|     return s_exit_emulation_activity; | ||||
| } | ||||
|  | ||||
| } // namespace IDCache | ||||
							
								
								
									
										11
									
								
								src/android/app/src/main/jni/id_cache.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/android/app/src/main/jni/id_cache.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <jni.h> | ||||
|  | ||||
| namespace IDCache { | ||||
|  | ||||
| JNIEnv* GetEnvForThread(); | ||||
| jclass GetNativeLibraryClass(); | ||||
| jmethodID GetExitEmulationActivity(); | ||||
|  | ||||
| } // namespace IDCache | ||||
							
								
								
									
										342
									
								
								src/android/app/src/main/jni/native.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										342
									
								
								src/android/app/src/main/jni/native.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,342 @@ | ||||
| #include <codecvt> | ||||
| #include <locale> | ||||
| #include <string> | ||||
| #include <string_view> | ||||
|  | ||||
| #include <android/api-level.h> | ||||
| #include <android/native_window_jni.h> | ||||
|  | ||||
| #include "common/detached_tasks.h" | ||||
| #include "common/logging/backend.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "common/scope_exit.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "core/cpu_manager.h" | ||||
| #include "core/file_sys/registered_cache.h" | ||||
| #include "core/file_sys/vfs_real.h" | ||||
| #include "core/hle/service/filesystem/filesystem.h" | ||||
| #include "core/perf_stats.h" | ||||
| #include "jni/emu_window/emu_window.h" | ||||
| #include "jni/id_cache.h" | ||||
| #include "video_core/rasterizer_interface.h" | ||||
|  | ||||
| namespace { | ||||
|  | ||||
| ANativeWindow* s_surf{}; | ||||
| std::unique_ptr<EmuWindow_Android> emu_window; | ||||
| std::atomic<bool> stop_run{true}; | ||||
| Core::System system_; | ||||
|  | ||||
| std::string UTF16ToUTF8(std::u16string_view input) { | ||||
|     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; | ||||
|     return convert.to_bytes(input.data(), input.data() + input.size()); | ||||
| } | ||||
|  | ||||
| std::string GetJString(JNIEnv* env, jstring jstr) { | ||||
|     if (!jstr) { | ||||
|         return {}; | ||||
|     } | ||||
|  | ||||
|     const jchar* jchars = env->GetStringChars(jstr, nullptr); | ||||
|     const jsize length = env->GetStringLength(jstr); | ||||
|     const std::u16string_view string_view(reinterpret_cast<const char16_t*>(jchars), length); | ||||
|     const std::string converted_string = UTF16ToUTF8(string_view); | ||||
|     env->ReleaseStringChars(jstr, jchars); | ||||
|  | ||||
|     return converted_string; | ||||
| } | ||||
|  | ||||
| } // Anonymous namespace | ||||
|  | ||||
| static Core::SystemResultStatus RunEmulation(const std::string& filepath) { | ||||
|     Common::Log::Initialize(); | ||||
|     Common::Log::SetColorConsoleBackendEnabled(true); | ||||
|     Common::Log::Start(); | ||||
|     Common::DetachedTasks detached_tasks; | ||||
|  | ||||
|     MicroProfileOnThreadCreate("EmuThread"); | ||||
|     SCOPE_EXIT({ MicroProfileShutdown(); }); | ||||
|  | ||||
|     LOG_INFO(Frontend, "starting"); | ||||
|  | ||||
|     if (filepath.empty()) { | ||||
|         LOG_CRITICAL(Frontend, "failed to load: filepath empty!"); | ||||
|         return Core::SystemResultStatus::ErrorLoader; | ||||
|     } | ||||
|  | ||||
|     system_.Initialize(); | ||||
|     system_.ApplySettings(); | ||||
|  | ||||
|     InputCommon::InputSubsystem input_subsystem{}; | ||||
|  | ||||
|     emu_window = std::make_unique<EmuWindow_Android>(&input_subsystem, s_surf); | ||||
|  | ||||
|     system_.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>()); | ||||
|     system_.SetFilesystem(std::make_shared<FileSys::RealVfsFilesystem>()); | ||||
|     system_.GetFileSystemController().CreateFactories(*system_.GetFilesystem()); | ||||
|  | ||||
|     const Core::SystemResultStatus load_result{system_.Load(*emu_window, filepath)}; | ||||
|  | ||||
|     if (load_result != Core::SystemResultStatus::Success) { | ||||
|         return load_result; | ||||
|     } | ||||
|  | ||||
|     system_.GPU().Start(); | ||||
|     system_.GetCpuManager().OnGpuReady(); | ||||
|     system_.RegisterExitCallback([&] { exit(0); }); | ||||
|  | ||||
|     void(system_.Run()); | ||||
|  | ||||
|     if (system_.DebuggerEnabled()) { | ||||
|         system_.InitializeDebugger(); | ||||
|     } | ||||
|  | ||||
|     stop_run = false; | ||||
|     while (!stop_run) { | ||||
|         std::this_thread::sleep_for(std::chrono::seconds(1)); | ||||
|     } | ||||
|  | ||||
|     system_.DetachDebugger(); | ||||
|     void(system_.Pause()); | ||||
|     system_.ShutdownMainProcess(); | ||||
|  | ||||
|     detached_tasks.WaitForAllTasks(); | ||||
|  | ||||
|     return Core::SystemResultStatus::Success; | ||||
| } | ||||
|  | ||||
| extern "C" { | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_SurfaceChanged(JNIEnv* env, | ||||
|                                                             [[maybe_unused]] jclass clazz, | ||||
|                                                             jobject surf) { | ||||
|     s_surf = ANativeWindow_fromSurface(env, surf); | ||||
|  | ||||
|     if (emu_window) { | ||||
|         emu_window->OnSurfaceChanged(s_surf); | ||||
|     } | ||||
|  | ||||
|     LOG_INFO(Frontend, "surface changed"); | ||||
| } | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_SurfaceDestroyed(JNIEnv* env, | ||||
|                                                               [[maybe_unused]] jclass clazz) { | ||||
|     ANativeWindow_release(s_surf); | ||||
|     s_surf = nullptr; | ||||
|     if (emu_window) { | ||||
|         emu_window->OnSurfaceChanged(s_surf); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_DoFrame(JNIEnv* env, [[maybe_unused]] jclass clazz) {} | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_NotifyOrientationChange(JNIEnv* env, | ||||
|                                                                      [[maybe_unused]] jclass clazz, | ||||
|                                                                      jint layout_option, | ||||
|                                                                      jint rotation) {} | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_SetUserDirectory( | ||||
|     [[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, | ||||
|     [[maybe_unused]] jstring j_directory) {} | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_UnPauseEmulation([[maybe_unused]] JNIEnv* env, | ||||
|                                                               [[maybe_unused]] jclass clazz) {} | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_PauseEmulation([[maybe_unused]] JNIEnv* env, | ||||
|                                                             [[maybe_unused]] jclass clazz) {} | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_StopEmulation([[maybe_unused]] JNIEnv* env, | ||||
|                                                            [[maybe_unused]] jclass clazz) {} | ||||
|  | ||||
| jboolean Java_org_citra_citra_1emu_NativeLibrary_IsRunning([[maybe_unused]] JNIEnv* env, | ||||
|                                                            [[maybe_unused]] jclass clazz) { | ||||
|     return static_cast<jboolean>(!stop_run); | ||||
| } | ||||
|  | ||||
| jboolean Java_org_citra_citra_1emu_NativeLibrary_onGamePadEvent([[maybe_unused]] JNIEnv* env, | ||||
|                                                                 [[maybe_unused]] jclass clazz, | ||||
|                                                                 [[maybe_unused]] jstring j_device, | ||||
|                                                                 jint j_button, jint action) { | ||||
|     emu_window->OnGamepadEvent(j_button, action != 0); | ||||
|     return static_cast<jboolean>(true); | ||||
| } | ||||
|  | ||||
| jboolean Java_org_citra_citra_1emu_NativeLibrary_onGamePadMoveEvent([[maybe_unused]] JNIEnv* env, | ||||
|                                                                     [[maybe_unused]] jclass clazz, | ||||
|                                                                     jstring j_device, jint axis, | ||||
|                                                                     jfloat x, jfloat y) { | ||||
|     // Clamp joystick movement to supported minimum and maximum. | ||||
|     x = std::clamp(x, -1.f, 1.f); | ||||
|     y = std::clamp(-y, -1.f, 1.f); | ||||
|  | ||||
|     // Clamp the input to a circle. | ||||
|     float r = x * x + y * y; | ||||
|     if (r > 1.0f) { | ||||
|         r = std::sqrt(r); | ||||
|         x /= r; | ||||
|         y /= r; | ||||
|     } | ||||
|     emu_window->OnGamepadMoveEvent(x, y); | ||||
|     return static_cast<jboolean>(false); | ||||
| } | ||||
|  | ||||
| jboolean Java_org_citra_citra_1emu_NativeLibrary_onGamePadAxisEvent([[maybe_unused]] JNIEnv* env, | ||||
|                                                                     [[maybe_unused]] jclass clazz, | ||||
|                                                                     jstring j_device, jint axis_id, | ||||
|                                                                     jfloat axis_val) { | ||||
|     return {}; | ||||
| } | ||||
|  | ||||
| jboolean Java_org_citra_citra_1emu_NativeLibrary_onTouchEvent([[maybe_unused]] JNIEnv* env, | ||||
|                                                               [[maybe_unused]] jclass clazz, | ||||
|                                                               jfloat x, jfloat y, | ||||
|                                                               jboolean pressed) { | ||||
|     return static_cast<jboolean>(emu_window->OnTouchEvent(x, y, pressed)); | ||||
| } | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_onTouchMoved([[maybe_unused]] JNIEnv* env, | ||||
|                                                           [[maybe_unused]] jclass clazz, jfloat x, | ||||
|                                                           jfloat y) { | ||||
|     emu_window->OnTouchMoved(x, y); | ||||
| } | ||||
|  | ||||
| jintArray Java_org_citra_citra_1emu_NativeLibrary_GetIcon([[maybe_unused]] JNIEnv* env, | ||||
|                                                           [[maybe_unused]] jclass clazz, | ||||
|                                                           [[maybe_unused]] jstring j_file) { | ||||
|     return {}; | ||||
| } | ||||
|  | ||||
| jstring Java_org_citra_citra_1emu_NativeLibrary_GetTitle([[maybe_unused]] JNIEnv* env, | ||||
|                                                          [[maybe_unused]] jclass clazz, | ||||
|                                                          [[maybe_unused]] jstring j_filename) { | ||||
|     return env->NewStringUTF(""); | ||||
| } | ||||
|  | ||||
| jstring Java_org_citra_citra_1emu_NativeLibrary_GetDescription([[maybe_unused]] JNIEnv* env, | ||||
|                                                                [[maybe_unused]] jclass clazz, | ||||
|                                                                jstring j_filename) { | ||||
|     return j_filename; | ||||
| } | ||||
|  | ||||
| jstring Java_org_citra_citra_1emu_NativeLibrary_GetGameId([[maybe_unused]] JNIEnv* env, | ||||
|                                                           [[maybe_unused]] jclass clazz, | ||||
|                                                           jstring j_filename) { | ||||
|     return j_filename; | ||||
| } | ||||
|  | ||||
| jstring Java_org_citra_citra_1emu_NativeLibrary_GetRegions([[maybe_unused]] JNIEnv* env, | ||||
|                                                            [[maybe_unused]] jclass clazz, | ||||
|                                                            [[maybe_unused]] jstring j_filename) { | ||||
|     return env->NewStringUTF(""); | ||||
| } | ||||
|  | ||||
| jstring Java_org_citra_citra_1emu_NativeLibrary_GetCompany([[maybe_unused]] JNIEnv* env, | ||||
|                                                            [[maybe_unused]] jclass clazz, | ||||
|                                                            [[maybe_unused]] jstring j_filename) { | ||||
|     return env->NewStringUTF(""); | ||||
| } | ||||
|  | ||||
| jstring Java_org_citra_citra_1emu_NativeLibrary_GetGitRevision([[maybe_unused]] JNIEnv* env, | ||||
|                                                                [[maybe_unused]] jclass clazz) { | ||||
|     return {}; | ||||
| } | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_CreateConfigFile | ||||
|     [[maybe_unused]] (JNIEnv* env, [[maybe_unused]] jclass clazz) {} | ||||
|  | ||||
| jint Java_org_citra_citra_1emu_NativeLibrary_DefaultCPUCore([[maybe_unused]] JNIEnv* env, | ||||
|                                                             [[maybe_unused]] jclass clazz) { | ||||
|     return {}; | ||||
| } | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_Run__Ljava_lang_String_2Ljava_lang_String_2Z( | ||||
|     [[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, [[maybe_unused]] jstring j_file, | ||||
|     [[maybe_unused]] jstring j_savestate, [[maybe_unused]] jboolean j_delete_savestate) {} | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_ReloadSettings([[maybe_unused]] JNIEnv* env, | ||||
|                                                             [[maybe_unused]] jclass clazz) {} | ||||
|  | ||||
| jstring Java_org_citra_citra_1emu_NativeLibrary_GetUserSetting([[maybe_unused]] JNIEnv* env, | ||||
|                                                                [[maybe_unused]] jclass clazz, | ||||
|                                                                jstring j_game_id, jstring j_section, | ||||
|                                                                jstring j_key) { | ||||
|     std::string_view game_id = env->GetStringUTFChars(j_game_id, 0); | ||||
|     std::string_view section = env->GetStringUTFChars(j_section, 0); | ||||
|     std::string_view key = env->GetStringUTFChars(j_key, 0); | ||||
|  | ||||
|     env->ReleaseStringUTFChars(j_game_id, game_id.data()); | ||||
|     env->ReleaseStringUTFChars(j_section, section.data()); | ||||
|     env->ReleaseStringUTFChars(j_key, key.data()); | ||||
|  | ||||
|     return env->NewStringUTF(""); | ||||
| } | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_SetUserSetting([[maybe_unused]] JNIEnv* env, | ||||
|                                                             [[maybe_unused]] jclass clazz, | ||||
|                                                             jstring j_game_id, jstring j_section, | ||||
|                                                             jstring j_key, jstring j_value) { | ||||
|     std::string_view game_id = env->GetStringUTFChars(j_game_id, 0); | ||||
|     std::string_view section = env->GetStringUTFChars(j_section, 0); | ||||
|     std::string_view key = env->GetStringUTFChars(j_key, 0); | ||||
|     std::string_view value = env->GetStringUTFChars(j_value, 0); | ||||
|  | ||||
|     env->ReleaseStringUTFChars(j_game_id, game_id.data()); | ||||
|     env->ReleaseStringUTFChars(j_section, section.data()); | ||||
|     env->ReleaseStringUTFChars(j_key, key.data()); | ||||
|     env->ReleaseStringUTFChars(j_value, value.data()); | ||||
| } | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_InitGameIni([[maybe_unused]] JNIEnv* env, | ||||
|                                                          [[maybe_unused]] jclass clazz, | ||||
|                                                          jstring j_game_id) { | ||||
|     std::string_view game_id = env->GetStringUTFChars(j_game_id, 0); | ||||
|  | ||||
|     env->ReleaseStringUTFChars(j_game_id, game_id.data()); | ||||
| } | ||||
|  | ||||
| jdoubleArray Java_org_citra_citra_1emu_NativeLibrary_GetPerfStats([[maybe_unused]] JNIEnv* env, | ||||
|                                                                   [[maybe_unused]] jclass clazz) { | ||||
|     jdoubleArray j_stats = env->NewDoubleArray(4); | ||||
|  | ||||
|     if (!stop_run && system_.IsPoweredOn()) { | ||||
|         const auto results = system_.GetAndResetPerfStats(); | ||||
|  | ||||
|         // Converting the structure into an array makes it easier to pass it to the frontend | ||||
|         double stats[4] = {results.system_fps, results.average_game_fps, results.frametime, | ||||
|                            results.emulation_speed}; | ||||
|  | ||||
|         env->SetDoubleArrayRegion(j_stats, 0, 4, stats); | ||||
|     } | ||||
|  | ||||
|     return j_stats; | ||||
| } | ||||
|  | ||||
| void Java_org_citra_citra_1emu_utils_DirectoryInitialization_SetSysDirectory( | ||||
|     [[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jstring j_path) {} | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_Run__Ljava_lang_String_2([[maybe_unused]] JNIEnv* env, | ||||
|                                                                       [[maybe_unused]] jclass clazz, | ||||
|                                                                       jstring j_path) { | ||||
|     const std::string path = GetJString(env, j_path); | ||||
|  | ||||
|     if (!stop_run) { | ||||
|         stop_run = true; | ||||
|     } | ||||
|  | ||||
|     const Core::SystemResultStatus result{RunEmulation(path)}; | ||||
|     if (result != Core::SystemResultStatus::Success) { | ||||
|         env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), | ||||
|                                   IDCache::GetExitEmulationActivity(), static_cast<int>(result)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void Java_org_citra_citra_1emu_NativeLibrary_LogDeviceInfo([[maybe_unused]] JNIEnv* env, | ||||
|                                                            [[maybe_unused]] jclass clazz) { | ||||
|     LOG_INFO(Frontend, "yuzu Version: {}-{}", Common::g_scm_branch, Common::g_scm_desc); | ||||
|     LOG_INFO(Frontend, "Host OS: Android API level {}", android_get_device_api_level()); | ||||
| } | ||||
|  | ||||
| } // extern "C" | ||||
							
								
								
									
										127
									
								
								src/android/app/src/main/jni/native.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								src/android/app/src/main/jni/native.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <jni.h> | ||||
|  | ||||
| // Function calls from the Java side | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_UnPauseEmulation(JNIEnv* env, | ||||
|                                                                                 jclass clazz); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_PauseEmulation(JNIEnv* env, | ||||
|                                                                               jclass clazz); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_StopEmulation(JNIEnv* env, | ||||
|                                                                              jclass clazz); | ||||
|  | ||||
| JNIEXPORT jboolean JNICALL Java_org_citra_citra_1emu_NativeLibrary_IsRunning(JNIEnv* env, | ||||
|                                                                              jclass clazz); | ||||
|  | ||||
| JNIEXPORT jboolean JNICALL Java_org_citra_citra_1emu_NativeLibrary_onGamePadEvent( | ||||
|     JNIEnv* env, jclass clazz, jstring j_device, jint j_button, jint action); | ||||
|  | ||||
| JNIEXPORT jboolean JNICALL Java_org_citra_citra_1emu_NativeLibrary_onGamePadMoveEvent( | ||||
|     JNIEnv* env, jclass clazz, jstring j_device, jint axis, jfloat x, jfloat y); | ||||
|  | ||||
| JNIEXPORT jboolean JNICALL Java_org_citra_citra_1emu_NativeLibrary_onGamePadAxisEvent( | ||||
|     JNIEnv* env, jclass clazz, jstring j_device, jint axis_id, jfloat axis_val); | ||||
|  | ||||
| JNIEXPORT jboolean JNICALL Java_org_citra_citra_1emu_NativeLibrary_onTouchEvent(JNIEnv* env, | ||||
|                                                                                 jclass clazz, | ||||
|                                                                                 jfloat x, jfloat y, | ||||
|                                                                                 jboolean pressed); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_onTouchMoved(JNIEnv* env, | ||||
|                                                                             jclass clazz, jfloat x, | ||||
|                                                                             jfloat y); | ||||
|  | ||||
| JNIEXPORT jintArray JNICALL Java_org_citra_citra_1emu_NativeLibrary_GetIcon(JNIEnv* env, | ||||
|                                                                             jclass clazz, | ||||
|                                                                             jstring j_file); | ||||
|  | ||||
| JNIEXPORT jstring JNICALL Java_org_citra_citra_1emu_NativeLibrary_GetTitle(JNIEnv* env, | ||||
|                                                                            jclass clazz, | ||||
|                                                                            jstring j_filename); | ||||
|  | ||||
| JNIEXPORT jstring JNICALL Java_org_citra_citra_1emu_NativeLibrary_GetDescription( | ||||
|     JNIEnv* env, jclass clazz, jstring j_filename); | ||||
|  | ||||
| JNIEXPORT jstring JNICALL Java_org_citra_citra_1emu_NativeLibrary_GetGameId(JNIEnv* env, | ||||
|                                                                             jclass clazz, | ||||
|                                                                             jstring j_filename); | ||||
|  | ||||
| JNIEXPORT jstring JNICALL Java_org_citra_citra_1emu_NativeLibrary_GetRegions(JNIEnv* env, | ||||
|                                                                              jclass clazz, | ||||
|                                                                              jstring j_filename); | ||||
|  | ||||
| JNIEXPORT jstring JNICALL Java_org_citra_citra_1emu_NativeLibrary_GetCompany(JNIEnv* env, | ||||
|                                                                              jclass clazz, | ||||
|                                                                              jstring j_filename); | ||||
|  | ||||
| JNIEXPORT jstring JNICALL Java_org_citra_citra_1emu_NativeLibrary_GetGitRevision(JNIEnv* env, | ||||
|                                                                                  jclass clazz); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_SetUserDirectory( | ||||
|     JNIEnv* env, jclass clazz, jstring j_directory); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_utils_DirectoryInitialization_SetSysDirectory( | ||||
|     JNIEnv* env, jclass clazz, jstring path_); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_SetSysDirectory(JNIEnv* env, | ||||
|                                                                                jclass clazz, | ||||
|                                                                                jstring path); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_CreateConfigFile(JNIEnv* env, | ||||
|                                                                                 jclass clazz); | ||||
|  | ||||
| JNIEXPORT jint JNICALL Java_org_citra_citra_1emu_NativeLibrary_DefaultCPUCore(JNIEnv* env, | ||||
|                                                                               jclass clazz); | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_SetProfiling(JNIEnv* env, | ||||
|                                                                             jclass clazz, | ||||
|                                                                             jboolean enable); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_WriteProfileResults(JNIEnv* env, | ||||
|                                                                                    jclass clazz); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_NotifyOrientationChange( | ||||
|     JNIEnv* env, jclass clazz, jint layout_option, jint rotation); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_Run__Ljava_lang_String_2( | ||||
|     JNIEnv* env, jclass clazz, jstring j_path); | ||||
|  | ||||
| JNIEXPORT void JNICALL | ||||
| Java_org_citra_citra_1emu_NativeLibrary_Run__Ljava_lang_String_2Ljava_lang_String_2Z( | ||||
|     JNIEnv* env, jclass clazz, jstring j_file, jstring j_savestate, jboolean j_delete_savestate); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_SurfaceChanged(JNIEnv* env, | ||||
|                                                                               jclass clazz, | ||||
|                                                                               jobject surf); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_SurfaceDestroyed(JNIEnv* env, | ||||
|                                                                                 jclass clazz); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_InitGameIni(JNIEnv* env, | ||||
|                                                                            jclass clazz, | ||||
|                                                                            jstring j_game_id); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_ReloadSettings(JNIEnv* env, | ||||
|                                                                               jclass clazz); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_SetUserSetting( | ||||
|     JNIEnv* env, jclass clazz, jstring j_game_id, jstring j_section, jstring j_key, | ||||
|     jstring j_value); | ||||
|  | ||||
| JNIEXPORT jstring JNICALL Java_org_citra_citra_1emu_NativeLibrary_GetUserSetting( | ||||
|     JNIEnv* env, jclass clazz, jstring game_id, jstring section, jstring key); | ||||
|  | ||||
| JNIEXPORT jdoubleArray JNICALL Java_org_citra_citra_1emu_NativeLibrary_GetPerfStats(JNIEnv* env, | ||||
|                                                                                     jclass clazz); | ||||
|  | ||||
| JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_LogDeviceInfo(JNIEnv* env, | ||||
|                                                                              jclass clazz); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user