Compare commits
8 Commits
android-21
...
android-21
Author | SHA1 | Date | |
---|---|---|---|
82359e986c | |||
5862b1df55 | |||
0da5c3912d | |||
fcae200396 | |||
ad63c5dc0e | |||
386bbc6495 | |||
d5e8c9d04f | |||
3f1290cee3 |
@ -1,8 +1,10 @@
|
|||||||
| Pull Request | Commit | Title | Author | Merged? |
|
| Pull Request | Commit | Title | Author | Merged? |
|
||||||
|----|----|----|----|----|
|
|----|----|----|----|----|
|
||||||
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`e3171486d`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`e3171486d`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
| [12760](https://github.com/yuzu-emu/yuzu-android//pull/12760) | [`2c33ba278`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [liamwhite](https://github.com/liamwhite/) | Yes |
|
| [12760](https://github.com/yuzu-emu/yuzu-android//pull/12760) | [`53f17ede1`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
| [12802](https://github.com/yuzu-emu/yuzu-android//pull/12802) | [`c5e88c654`](https://github.com/yuzu-emu/yuzu-android//pull/12802/files) | service: mii: Migrate service to new interface | [german77](https://github.com/german77/) | Yes |
|
| [12802](https://github.com/yuzu-emu/yuzu-android//pull/12802) | [`c5e88c654`](https://github.com/yuzu-emu/yuzu-android//pull/12802/files) | service: mii: Migrate service to new interface | [german77](https://github.com/german77/) | Yes |
|
||||||
|
| [12826](https://github.com/yuzu-emu/yuzu-android//pull/12826) | [`2d8f80b65`](https://github.com/yuzu-emu/yuzu-android//pull/12826/files) | android: Show system driver information | [t895](https://github.com/t895/) | Yes |
|
||||||
|
| [12827](https://github.com/yuzu-emu/yuzu-android//pull/12827) | [`c770af9b1`](https://github.com/yuzu-emu/yuzu-android//pull/12827/files) | android: Disable focus on loading card | [t895](https://github.com/t895/) | Yes |
|
||||||
|
|
||||||
|
|
||||||
End of merge log. You can find the original README.md below the break.
|
End of merge log. You can find the original README.md below the break.
|
||||||
|
@ -261,7 +261,7 @@ object NativeLibrary {
|
|||||||
/**
|
/**
|
||||||
* Begins emulation.
|
* Begins emulation.
|
||||||
*/
|
*/
|
||||||
external fun run(path: String?)
|
external fun run(path: String?, programIndex: Int = 0)
|
||||||
|
|
||||||
// Surface Handling
|
// Surface Handling
|
||||||
external fun surfaceChanged(surf: Surface?)
|
external fun surfaceChanged(surf: Surface?)
|
||||||
@ -489,6 +489,12 @@ object NativeLibrary {
|
|||||||
sEmulationActivity.get()!!.onEmulationStopped(status)
|
sEmulationActivity.get()!!.onEmulationStopped(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
@JvmStatic
|
||||||
|
fun onProgramChanged(programIndex: Int) {
|
||||||
|
sEmulationActivity.get()!!.onProgramChanged(programIndex)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs the Yuzu version, Android version and, CPU.
|
* Logs the Yuzu version, Android version and, CPU.
|
||||||
*/
|
*/
|
||||||
|
@ -76,7 +76,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
|||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
stopForegroundService(this)
|
stopForegroundService(this)
|
||||||
emulationViewModel.clear()
|
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,9 +445,14 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onEmulationStopped(status: Int) {
|
fun onEmulationStopped(status: Int) {
|
||||||
if (status == 0) {
|
if (status == 0 && emulationViewModel.programChanged.value == -1) {
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
emulationViewModel.setEmulationStopped(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onProgramChanged(programIndex: Int) {
|
||||||
|
emulationViewModel.setProgramChanged(programIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startMotionSensorListener() {
|
private fun startMotionSensorListener() {
|
||||||
|
@ -424,10 +424,38 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||||
|
emulationViewModel.programChanged.collect {
|
||||||
|
if (it != 0) {
|
||||||
|
emulationViewModel.setEmulationStarted(false)
|
||||||
|
binding.drawerLayout.close()
|
||||||
|
binding.drawerLayout
|
||||||
|
.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
|
||||||
|
ViewUtils.hideView(binding.surfaceInputOverlay)
|
||||||
|
ViewUtils.showView(binding.loadingIndicator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||||
|
emulationViewModel.emulationStopped.collect {
|
||||||
|
if (it && emulationViewModel.programChanged.value != -1) {
|
||||||
|
if (perfStatsUpdater != null) {
|
||||||
|
perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!)
|
||||||
|
}
|
||||||
|
emulationState.changeProgram(emulationViewModel.programChanged.value)
|
||||||
|
emulationViewModel.setProgramChanged(-1)
|
||||||
|
emulationViewModel.setEmulationStopped(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startEmulation() {
|
private fun startEmulation(programIndex: Int = 0) {
|
||||||
if (!NativeLibrary.isRunning() && !NativeLibrary.isPaused()) {
|
if (!NativeLibrary.isRunning() && !NativeLibrary.isPaused()) {
|
||||||
if (!DirectoryInitialization.areDirectoriesReady) {
|
if (!DirectoryInitialization.areDirectoriesReady) {
|
||||||
DirectoryInitialization.start()
|
DirectoryInitialization.start()
|
||||||
@ -435,7 +463,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
|
|
||||||
updateScreenLayout()
|
updateScreenLayout()
|
||||||
|
|
||||||
emulationState.run(emulationActivity!!.isActivityRecreated)
|
emulationState.run(emulationActivity!!.isActivityRecreated, programIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -833,6 +861,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
) {
|
) {
|
||||||
private var state: State
|
private var state: State
|
||||||
private var surface: Surface? = null
|
private var surface: Surface? = null
|
||||||
|
lateinit var emulationThread: Thread
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Starting state is stopped.
|
// Starting state is stopped.
|
||||||
@ -878,7 +907,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun run(isActivityRecreated: Boolean) {
|
fun run(isActivityRecreated: Boolean, programIndex: Int = 0) {
|
||||||
if (isActivityRecreated) {
|
if (isActivityRecreated) {
|
||||||
if (NativeLibrary.isRunning()) {
|
if (NativeLibrary.isRunning()) {
|
||||||
state = State.PAUSED
|
state = State.PAUSED
|
||||||
@ -889,10 +918,20 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
|
|
||||||
// If the surface is set, run now. Otherwise, wait for it to get set.
|
// If the surface is set, run now. Otherwise, wait for it to get set.
|
||||||
if (surface != null) {
|
if (surface != null) {
|
||||||
runWithValidSurface()
|
runWithValidSurface(programIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun changeProgram(programIndex: Int) {
|
||||||
|
emulationThread.join()
|
||||||
|
emulationThread = Thread({
|
||||||
|
Log.debug("[EmulationFragment] Starting emulation thread.")
|
||||||
|
NativeLibrary.run(gamePath, programIndex)
|
||||||
|
}, "NativeEmulation")
|
||||||
|
emulationThread.start()
|
||||||
|
}
|
||||||
|
|
||||||
// Surface callbacks
|
// Surface callbacks
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun newSurface(surface: Surface?) {
|
fun newSurface(surface: Surface?) {
|
||||||
@ -932,7 +971,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runWithValidSurface() {
|
private fun runWithValidSurface(programIndex: Int = 0) {
|
||||||
NativeLibrary.surfaceChanged(surface)
|
NativeLibrary.surfaceChanged(surface)
|
||||||
if (!emulationCanStart.invoke()) {
|
if (!emulationCanStart.invoke()) {
|
||||||
return
|
return
|
||||||
@ -940,9 +979,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
|
|
||||||
when (state) {
|
when (state) {
|
||||||
State.STOPPED -> {
|
State.STOPPED -> {
|
||||||
val emulationThread = Thread({
|
emulationThread = Thread({
|
||||||
Log.debug("[EmulationFragment] Starting emulation thread.")
|
Log.debug("[EmulationFragment] Starting emulation thread.")
|
||||||
NativeLibrary.run(gamePath)
|
NativeLibrary.run(gamePath, programIndex)
|
||||||
}, "NativeEmulation")
|
}, "NativeEmulation")
|
||||||
emulationThread.start()
|
emulationThread.start()
|
||||||
}
|
}
|
||||||
|
@ -66,10 +66,13 @@ class DriverViewModel : ViewModel() {
|
|||||||
|
|
||||||
fun updateDriverList() {
|
fun updateDriverList() {
|
||||||
val selectedDriver = GpuDriverHelper.customDriverSettingData
|
val selectedDriver = GpuDriverHelper.customDriverSettingData
|
||||||
|
val systemDriverData = GpuDriverHelper.getSystemDriverInfo()
|
||||||
val newDriverList = mutableListOf(
|
val newDriverList = mutableListOf(
|
||||||
Driver(
|
Driver(
|
||||||
selectedDriver == GpuDriverMetadata(),
|
selectedDriver == GpuDriverMetadata(),
|
||||||
YuzuApplication.appContext.getString(R.string.system_gpu_driver)
|
YuzuApplication.appContext.getString(R.string.system_gpu_driver),
|
||||||
|
systemDriverData?.get(0) ?: "",
|
||||||
|
systemDriverData?.get(1) ?: ""
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
driverData.forEach {
|
driverData.forEach {
|
||||||
|
@ -15,6 +15,12 @@ class EmulationViewModel : ViewModel() {
|
|||||||
val isEmulationStopping: StateFlow<Boolean> get() = _isEmulationStopping
|
val isEmulationStopping: StateFlow<Boolean> get() = _isEmulationStopping
|
||||||
private val _isEmulationStopping = MutableStateFlow(false)
|
private val _isEmulationStopping = MutableStateFlow(false)
|
||||||
|
|
||||||
|
private val _emulationStopped = MutableStateFlow(false)
|
||||||
|
val emulationStopped = _emulationStopped.asStateFlow()
|
||||||
|
|
||||||
|
private val _programChanged = MutableStateFlow(-1)
|
||||||
|
val programChanged = _programChanged.asStateFlow()
|
||||||
|
|
||||||
val shaderProgress: StateFlow<Int> get() = _shaderProgress
|
val shaderProgress: StateFlow<Int> get() = _shaderProgress
|
||||||
private val _shaderProgress = MutableStateFlow(0)
|
private val _shaderProgress = MutableStateFlow(0)
|
||||||
|
|
||||||
@ -35,6 +41,17 @@ class EmulationViewModel : ViewModel() {
|
|||||||
_isEmulationStopping.value = value
|
_isEmulationStopping.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setEmulationStopped(value: Boolean) {
|
||||||
|
if (value) {
|
||||||
|
_emulationStarted.value = false
|
||||||
|
}
|
||||||
|
_emulationStopped.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setProgramChanged(programIndex: Int) {
|
||||||
|
_programChanged.value = programIndex
|
||||||
|
}
|
||||||
|
|
||||||
fun setShaderProgress(progress: Int) {
|
fun setShaderProgress(progress: Int) {
|
||||||
_shaderProgress.value = progress
|
_shaderProgress.value = progress
|
||||||
}
|
}
|
||||||
@ -56,20 +73,4 @@ class EmulationViewModel : ViewModel() {
|
|||||||
fun setDrawerOpen(value: Boolean) {
|
fun setDrawerOpen(value: Boolean) {
|
||||||
_drawerOpen.value = value
|
_drawerOpen.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clear() {
|
|
||||||
setEmulationStarted(false)
|
|
||||||
setIsEmulationStopping(false)
|
|
||||||
setShaderProgress(0)
|
|
||||||
setTotalShaders(0)
|
|
||||||
setShaderMessage("")
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val KEY_EMULATION_STARTED = "EmulationStarted"
|
|
||||||
const val KEY_IS_EMULATION_STOPPING = "IsEmulationStarting"
|
|
||||||
const val KEY_SHADER_PROGRESS = "ShaderProgress"
|
|
||||||
const val KEY_TOTAL_SHADERS = "TotalShaders"
|
|
||||||
const val KEY_SHADER_MESSAGE = "ShaderMessage"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
|
|
||||||
package org.yuzu.yuzu_emu.utils
|
package org.yuzu.yuzu_emu.utils
|
||||||
|
|
||||||
|
import android.graphics.SurfaceTexture
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.view.Surface
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import org.yuzu.yuzu_emu.NativeLibrary
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
@ -195,6 +197,11 @@ object GpuDriverHelper {
|
|||||||
|
|
||||||
external fun supportsCustomDriverLoading(): Boolean
|
external fun supportsCustomDriverLoading(): Boolean
|
||||||
|
|
||||||
|
external fun getSystemDriverInfo(
|
||||||
|
surface: Surface = Surface(SurfaceTexture(true)),
|
||||||
|
hookLibPath: String = GpuDriverHelper.hookLibPath!!
|
||||||
|
): Array<String>?
|
||||||
|
|
||||||
// Parse the custom driver metadata to retrieve the name.
|
// Parse the custom driver metadata to retrieve the name.
|
||||||
val installedCustomDriverData: GpuDriverMetadata
|
val installedCustomDriverData: GpuDriverMetadata
|
||||||
get() = GpuDriverMetadata(File(driverInstallationPath + META_JSON_FILENAME))
|
get() = GpuDriverMetadata(File(driverInstallationPath + META_JSON_FILENAME))
|
||||||
|
@ -22,7 +22,7 @@ add_library(yuzu-android SHARED
|
|||||||
|
|
||||||
set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
|
set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
|
||||||
|
|
||||||
target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common)
|
target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common Vulkan::Headers)
|
||||||
target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log)
|
target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log)
|
||||||
if (ARCHITECTURE_arm64)
|
if (ARCHITECTURE_arm64)
|
||||||
target_link_libraries(yuzu-android PRIVATE adrenotools)
|
target_link_libraries(yuzu-android PRIVATE adrenotools)
|
||||||
|
@ -19,6 +19,7 @@ static jmethodID s_exit_emulation_activity;
|
|||||||
static jmethodID s_disk_cache_load_progress;
|
static jmethodID s_disk_cache_load_progress;
|
||||||
static jmethodID s_on_emulation_started;
|
static jmethodID s_on_emulation_started;
|
||||||
static jmethodID s_on_emulation_stopped;
|
static jmethodID s_on_emulation_stopped;
|
||||||
|
static jmethodID s_on_program_changed;
|
||||||
|
|
||||||
static jclass s_game_class;
|
static jclass s_game_class;
|
||||||
static jmethodID s_game_constructor;
|
static jmethodID s_game_constructor;
|
||||||
@ -123,6 +124,10 @@ jmethodID GetOnEmulationStopped() {
|
|||||||
return s_on_emulation_stopped;
|
return s_on_emulation_stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jmethodID GetOnProgramChanged() {
|
||||||
|
return s_on_program_changed;
|
||||||
|
}
|
||||||
|
|
||||||
jclass GetGameClass() {
|
jclass GetGameClass() {
|
||||||
return s_game_class;
|
return s_game_class;
|
||||||
}
|
}
|
||||||
@ -306,6 +311,8 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
|||||||
env->GetStaticMethodID(s_native_library_class, "onEmulationStarted", "()V");
|
env->GetStaticMethodID(s_native_library_class, "onEmulationStarted", "()V");
|
||||||
s_on_emulation_stopped =
|
s_on_emulation_stopped =
|
||||||
env->GetStaticMethodID(s_native_library_class, "onEmulationStopped", "(I)V");
|
env->GetStaticMethodID(s_native_library_class, "onEmulationStopped", "(I)V");
|
||||||
|
s_on_program_changed =
|
||||||
|
env->GetStaticMethodID(s_native_library_class, "onProgramChanged", "(I)V");
|
||||||
|
|
||||||
const jclass game_class = env->FindClass("org/yuzu/yuzu_emu/model/Game");
|
const jclass game_class = env->FindClass("org/yuzu/yuzu_emu/model/Game");
|
||||||
s_game_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_class));
|
s_game_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_class));
|
||||||
|
@ -19,6 +19,7 @@ jmethodID GetExitEmulationActivity();
|
|||||||
jmethodID GetDiskCacheLoadProgress();
|
jmethodID GetDiskCacheLoadProgress();
|
||||||
jmethodID GetOnEmulationStarted();
|
jmethodID GetOnEmulationStarted();
|
||||||
jmethodID GetOnEmulationStopped();
|
jmethodID GetOnEmulationStopped();
|
||||||
|
jmethodID GetOnProgramChanged();
|
||||||
|
|
||||||
jclass GetGameClass();
|
jclass GetGameClass();
|
||||||
jmethodID GetGameConstructor();
|
jmethodID GetGameConstructor();
|
||||||
|
@ -61,6 +61,9 @@
|
|||||||
#include "jni/id_cache.h"
|
#include "jni/id_cache.h"
|
||||||
#include "jni/native.h"
|
#include "jni/native.h"
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
|
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan_instance.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan_surface.h"
|
||||||
|
|
||||||
#define jconst [[maybe_unused]] const auto
|
#define jconst [[maybe_unused]] const auto
|
||||||
#define jauto [[maybe_unused]] auto
|
#define jauto [[maybe_unused]] auto
|
||||||
@ -215,7 +218,8 @@ void EmulationSession::SetAppletId(int applet_id) {
|
|||||||
static_cast<Service::AM::AppletId>(m_applet_id));
|
static_cast<Service::AM::AppletId>(m_applet_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath) {
|
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
|
||||||
|
const std::size_t program_index) {
|
||||||
std::scoped_lock lock(m_mutex);
|
std::scoped_lock lock(m_mutex);
|
||||||
|
|
||||||
// Create the render window.
|
// Create the render window.
|
||||||
@ -247,6 +251,7 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
|
|||||||
// Load the ROM.
|
// Load the ROM.
|
||||||
Service::AM::FrontendAppletParameters params{
|
Service::AM::FrontendAppletParameters params{
|
||||||
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
|
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
|
||||||
|
.program_index = static_cast<s32>(program_index),
|
||||||
};
|
};
|
||||||
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
|
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
|
||||||
if (m_load_result != Core::SystemResultStatus::Success) {
|
if (m_load_result != Core::SystemResultStatus::Success) {
|
||||||
@ -258,6 +263,12 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
|
|||||||
m_system.GetCpuManager().OnGpuReady();
|
m_system.GetCpuManager().OnGpuReady();
|
||||||
m_system.RegisterExitCallback([&] { HaltEmulation(); });
|
m_system.RegisterExitCallback([&] { HaltEmulation(); });
|
||||||
|
|
||||||
|
// Register an ExecuteProgram callback such that Core can execute a sub-program
|
||||||
|
m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) {
|
||||||
|
m_next_program_index = program_index_;
|
||||||
|
EmulationSession::GetInstance().HaltEmulation();
|
||||||
|
});
|
||||||
|
|
||||||
OnEmulationStarted();
|
OnEmulationStarted();
|
||||||
return Core::SystemResultStatus::Success;
|
return Core::SystemResultStatus::Success;
|
||||||
}
|
}
|
||||||
@ -265,6 +276,11 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
|
|||||||
void EmulationSession::ShutdownEmulation() {
|
void EmulationSession::ShutdownEmulation() {
|
||||||
std::scoped_lock lock(m_mutex);
|
std::scoped_lock lock(m_mutex);
|
||||||
|
|
||||||
|
if (m_next_program_index != -1) {
|
||||||
|
ChangeProgram(m_next_program_index);
|
||||||
|
m_next_program_index = -1;
|
||||||
|
}
|
||||||
|
|
||||||
m_is_running = false;
|
m_is_running = false;
|
||||||
|
|
||||||
// Unload user input.
|
// Unload user input.
|
||||||
@ -415,6 +431,12 @@ void EmulationSession::OnEmulationStopped(Core::SystemResultStatus result) {
|
|||||||
static_cast<jint>(result));
|
static_cast<jint>(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmulationSession::ChangeProgram(std::size_t program_index) {
|
||||||
|
JNIEnv* env = IDCache::GetEnvForThread();
|
||||||
|
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnProgramChanged(),
|
||||||
|
static_cast<jint>(program_index));
|
||||||
|
}
|
||||||
|
|
||||||
u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
|
u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
|
||||||
auto program_id_string = GetJString(env, jprogramId);
|
auto program_id_string = GetJString(env, jprogramId);
|
||||||
try {
|
try {
|
||||||
@ -424,7 +446,8 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
|
static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
||||||
|
const size_t program_index = 0) {
|
||||||
MicroProfileOnThreadCreate("EmuThread");
|
MicroProfileOnThreadCreate("EmuThread");
|
||||||
SCOPE_EXIT({ MicroProfileShutdown(); });
|
SCOPE_EXIT({ MicroProfileShutdown(); });
|
||||||
|
|
||||||
@ -437,7 +460,7 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
|
|||||||
|
|
||||||
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
|
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
|
||||||
|
|
||||||
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath);
|
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index);
|
||||||
if (result != Core::SystemResultStatus::Success) {
|
if (result != Core::SystemResultStatus::Success) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -534,6 +557,37 @@ jboolean JNICALL Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_supportsCustomDri
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo(
|
||||||
|
JNIEnv* env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) {
|
||||||
|
const char* file_redirect_dir_{};
|
||||||
|
int featureFlags{};
|
||||||
|
std::string hook_lib_dir = GetJString(env, j_hook_lib_dir);
|
||||||
|
auto handle = adrenotools_open_libvulkan(RTLD_NOW, featureFlags, nullptr, hook_lib_dir.c_str(),
|
||||||
|
nullptr, nullptr, file_redirect_dir_, nullptr);
|
||||||
|
auto driver_library = std::make_shared<Common::DynamicLibrary>(handle);
|
||||||
|
InputCommon::InputSubsystem input_subsystem;
|
||||||
|
auto m_window = std::make_unique<EmuWindow_Android>(
|
||||||
|
&input_subsystem, ANativeWindow_fromSurface(env, j_surf), driver_library);
|
||||||
|
|
||||||
|
Vulkan::vk::InstanceDispatch dld;
|
||||||
|
Vulkan::vk::Instance vk_instance = Vulkan::CreateInstance(
|
||||||
|
*driver_library, dld, VK_API_VERSION_1_1, Core::Frontend::WindowSystemType::Android);
|
||||||
|
|
||||||
|
auto surface = Vulkan::CreateSurface(vk_instance, m_window->GetWindowInfo());
|
||||||
|
|
||||||
|
auto device = Vulkan::CreateDevice(vk_instance, dld, *surface);
|
||||||
|
|
||||||
|
auto driver_version = device.GetDriverVersion();
|
||||||
|
auto version_string =
|
||||||
|
fmt::format("{}.{}.{}", VK_API_VERSION_MAJOR(driver_version),
|
||||||
|
VK_API_VERSION_MINOR(driver_version), VK_API_VERSION_PATCH(driver_version));
|
||||||
|
|
||||||
|
jobjectArray j_driver_info =
|
||||||
|
env->NewObjectArray(2, IDCache::GetStringClass(), ToJString(env, version_string));
|
||||||
|
env->SetObjectArrayElement(j_driver_info, 1, ToJString(env, device.GetDriverName()));
|
||||||
|
return j_driver_info;
|
||||||
|
}
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) {
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) {
|
||||||
Core::Crypto::KeyManager::Instance().ReloadKeys();
|
Core::Crypto::KeyManager::Instance().ReloadKeys();
|
||||||
return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().AreKeysLoaded());
|
return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().AreKeysLoaded());
|
||||||
@ -702,11 +756,11 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj
|
|||||||
Settings::LogSettings();
|
Settings::LogSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2(JNIEnv* env, jclass clazz,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
|
||||||
jstring j_path) {
|
jint j_program_index) {
|
||||||
const std::string path = GetJString(env, j_path);
|
const std::string path = GetJString(env, j_path);
|
||||||
|
|
||||||
const Core::SystemResultStatus result{RunEmulation(path)};
|
const Core::SystemResultStatus result{RunEmulation(path, j_program_index)};
|
||||||
if (result != Core::SystemResultStatus::Success) {
|
if (result != Core::SystemResultStatus::Success) {
|
||||||
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
||||||
IDCache::GetExitEmulationActivity(), static_cast<int>(result));
|
IDCache::GetExitEmulationActivity(), static_cast<int>(result));
|
||||||
|
@ -46,7 +46,8 @@ public:
|
|||||||
void ConfigureFilesystemProvider(const std::string& filepath);
|
void ConfigureFilesystemProvider(const std::string& filepath);
|
||||||
void InitializeSystem(bool reload);
|
void InitializeSystem(bool reload);
|
||||||
void SetAppletId(int applet_id);
|
void SetAppletId(int applet_id);
|
||||||
Core::SystemResultStatus InitializeEmulation(const std::string& filepath);
|
Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
|
||||||
|
const std::size_t program_index = 0);
|
||||||
|
|
||||||
bool IsHandheldOnly();
|
bool IsHandheldOnly();
|
||||||
void SetDeviceType([[maybe_unused]] int index, int type);
|
void SetDeviceType([[maybe_unused]] int index, int type);
|
||||||
@ -61,6 +62,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
|
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
|
||||||
static void OnEmulationStopped(Core::SystemResultStatus result);
|
static void OnEmulationStopped(Core::SystemResultStatus result);
|
||||||
|
static void ChangeProgram(std::size_t program_index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Window management
|
// Window management
|
||||||
@ -86,4 +88,7 @@ private:
|
|||||||
// Synchronization
|
// Synchronization
|
||||||
std::condition_variable_any m_cv;
|
std::condition_variable_any m_cv;
|
||||||
mutable std::mutex m_mutex;
|
mutable std::mutex m_mutex;
|
||||||
|
|
||||||
|
// Program index for next boot
|
||||||
|
std::atomic<s32> m_next_program_index = -1;
|
||||||
};
|
};
|
||||||
|
@ -34,8 +34,10 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
|
android:focusable="false"
|
||||||
android:defaultFocusHighlightEnabled="false"
|
android:defaultFocusHighlightEnabled="false"
|
||||||
android:clickable="false">
|
android:clickable="false"
|
||||||
|
app:rippleColor="@android:color/transparent">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/loading_layout"
|
android:id="@+id/loading_layout"
|
||||||
|
Reference in New Issue
Block a user