summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/android/app/src/main/jni/CMakeLists.txt1
-rw-r--r--src/android/app/src/main/jni/native.cpp713
-rw-r--r--src/android/app/src/main/jni/native.h84
3 files changed, 392 insertions, 406 deletions
diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt
index e15d1480b..7193903da 100644
--- a/src/android/app/src/main/jni/CMakeLists.txt
+++ b/src/android/app/src/main/jni/CMakeLists.txt
@@ -14,6 +14,7 @@ add_library(yuzu-android SHARED
id_cache.cpp
id_cache.h
native.cpp
+ native.h
native_config.cpp
uisettings.cpp
)
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 598f4e8bf..629be3d81 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -33,7 +33,6 @@
#include "core/crypto/key_manager.h"
#include "core/file_sys/card_image.h"
#include "core/file_sys/content_archive.h"
-#include "core/file_sys/registered_cache.h"
#include "core/file_sys/submission_package.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_real.h"
@@ -48,514 +47,416 @@
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "core/hid/hid_types.h"
-#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h"
-#include "core/perf_stats.h"
#include "jni/android_common/android_common.h"
-#include "jni/applets/software_keyboard.h"
#include "jni/config.h"
-#include "jni/emu_window/emu_window.h"
#include "jni/id_cache.h"
-#include "video_core/rasterizer_interface.h"
+#include "jni/native.h"
#include "video_core/renderer_base.h"
#define jconst [[maybe_unused]] const auto
#define jauto [[maybe_unused]] auto
-namespace {
+static EmulationSession s_instance;
-class EmulationSession final {
-public:
- EmulationSession() {
- m_vfs = std::make_shared<FileSys::RealVfsFilesystem>();
- }
-
- ~EmulationSession() = default;
-
- static EmulationSession& GetInstance() {
- return s_instance;
- }
-
- const Core::System& System() const {
- return m_system;
- }
+EmulationSession::EmulationSession() {
+ m_vfs = std::make_shared<FileSys::RealVfsFilesystem>();
+}
- Core::System& System() {
- return m_system;
- }
+EmulationSession& EmulationSession::GetInstance() {
+ return s_instance;
+}
- const EmuWindow_Android& Window() const {
- return *m_window;
- }
+const Core::System& EmulationSession::System() const {
+ return m_system;
+}
- EmuWindow_Android& Window() {
- return *m_window;
- }
+Core::System& EmulationSession::System() {
+ return m_system;
+}
- ANativeWindow* NativeWindow() const {
- return m_native_window;
- }
+const EmuWindow_Android& EmulationSession::Window() const {
+ return *m_window;
+}
- void SetNativeWindow(ANativeWindow* native_window) {
- m_native_window = native_window;
- }
+EmuWindow_Android& EmulationSession::Window() {
+ return *m_window;
+}
- int InstallFileToNand(std::string filename, std::string file_extension) {
- jconst copy_func = [](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest,
- std::size_t block_size) {
- if (src == nullptr || dest == nullptr) {
- return false;
- }
- if (!dest->Resize(src->GetSize())) {
- return false;
- }
+ANativeWindow* EmulationSession::NativeWindow() const {
+ return m_native_window;
+}
- using namespace Common::Literals;
- [[maybe_unused]] std::vector<u8> buffer(1_MiB);
+void EmulationSession::SetNativeWindow(ANativeWindow* native_window) {
+ m_native_window = native_window;
+}
- for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) {
- jconst read = src->Read(buffer.data(), buffer.size(), i);
- dest->Write(buffer.data(), read, i);
- }
- return true;
- };
-
- enum InstallResult {
- Success = 0,
- SuccessFileOverwritten = 1,
- InstallError = 2,
- ErrorBaseGame = 3,
- ErrorFilenameExtension = 4,
- };
-
- m_system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
- m_system.GetFileSystemController().CreateFactories(*m_vfs);
-
- [[maybe_unused]] std::shared_ptr<FileSys::NSP> nsp;
- if (file_extension == "nsp") {
- nsp = std::make_shared<FileSys::NSP>(m_vfs->OpenFile(filename, FileSys::Mode::Read));
- if (nsp->IsExtractedType()) {
- return InstallError;
- }
- } else {
- return ErrorFilenameExtension;
+int EmulationSession::InstallFileToNand(std::string filename, std::string file_extension) {
+ jconst copy_func = [](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest,
+ std::size_t block_size) {
+ if (src == nullptr || dest == nullptr) {
+ return false;
}
-
- if (!nsp) {
- return InstallError;
+ if (!dest->Resize(src->GetSize())) {
+ return false;
}
- if (nsp->GetStatus() != Loader::ResultStatus::Success) {
- return InstallError;
- }
+ using namespace Common::Literals;
+ [[maybe_unused]] std::vector<u8> buffer(1_MiB);
- jconst res = m_system.GetFileSystemController().GetUserNANDContents()->InstallEntry(
- *nsp, true, copy_func);
-
- switch (res) {
- case FileSys::InstallResult::Success:
- return Success;
- case FileSys::InstallResult::OverwriteExisting:
- return SuccessFileOverwritten;
- case FileSys::InstallResult::ErrorBaseInstall:
- return ErrorBaseGame;
- default:
- return InstallError;
+ for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) {
+ jconst read = src->Read(buffer.data(), buffer.size(), i);
+ dest->Write(buffer.data(), read, i);
}
- }
+ return true;
+ };
- void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir,
- const std::string& custom_driver_name,
- const std::string& file_redirect_dir) {
-#ifdef ARCHITECTURE_arm64
- void* handle{};
- const char* file_redirect_dir_{};
- int featureFlags{};
-
- // Enable driver file redirection when renderer debugging is enabled.
- if (Settings::values.renderer_debug && file_redirect_dir.size()) {
- featureFlags |= ADRENOTOOLS_DRIVER_FILE_REDIRECT;
- file_redirect_dir_ = file_redirect_dir.c_str();
- }
+ enum InstallResult {
+ Success = 0,
+ SuccessFileOverwritten = 1,
+ InstallError = 2,
+ ErrorBaseGame = 3,
+ ErrorFilenameExtension = 4,
+ };
- // Try to load a custom driver.
- if (custom_driver_name.size()) {
- handle = adrenotools_open_libvulkan(
- RTLD_NOW, featureFlags | ADRENOTOOLS_DRIVER_CUSTOM, nullptr, hook_lib_dir.c_str(),
- custom_driver_dir.c_str(), custom_driver_name.c_str(), file_redirect_dir_, nullptr);
- }
+ m_system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
+ m_system.GetFileSystemController().CreateFactories(*m_vfs);
- // Try to load the system driver.
- if (!handle) {
- handle =
- adrenotools_open_libvulkan(RTLD_NOW, featureFlags, nullptr, hook_lib_dir.c_str(),
- nullptr, nullptr, file_redirect_dir_, nullptr);
+ [[maybe_unused]] std::shared_ptr<FileSys::NSP> nsp;
+ if (file_extension == "nsp") {
+ nsp = std::make_shared<FileSys::NSP>(m_vfs->OpenFile(filename, FileSys::Mode::Read));
+ if (nsp->IsExtractedType()) {
+ return InstallError;
}
-
- m_vulkan_library = std::make_shared<Common::DynamicLibrary>(handle);
-#endif
+ } else {
+ return ErrorFilenameExtension;
}
- bool IsRunning() const {
- return m_is_running;
+ if (!nsp) {
+ return InstallError;
}
- bool IsPaused() const {
- return m_is_running && m_is_paused;
+ if (nsp->GetStatus() != Loader::ResultStatus::Success) {
+ return InstallError;
}
- const Core::PerfStatsResults& PerfStats() const {
- std::scoped_lock m_perf_stats_lock(m_perf_stats_mutex);
- return m_perf_stats;
- }
+ jconst res = m_system.GetFileSystemController().GetUserNANDContents()->InstallEntry(*nsp, true,
+ copy_func);
- void SurfaceChanged() {
- if (!IsRunning()) {
- return;
- }
- m_window->OnSurfaceChanged(m_native_window);
+ switch (res) {
+ case FileSys::InstallResult::Success:
+ return Success;
+ case FileSys::InstallResult::OverwriteExisting:
+ return SuccessFileOverwritten;
+ case FileSys::InstallResult::ErrorBaseInstall:
+ return ErrorBaseGame;
+ default:
+ return InstallError;
}
+}
- void ConfigureFilesystemProvider(const std::string& filepath) {
- const auto file = m_system.GetFilesystem()->OpenFile(filepath, FileSys::Mode::Read);
- if (!file) {
- return;
- }
-
- auto loader = Loader::GetLoader(m_system, file);
- if (!loader) {
- return;
- }
-
- const auto file_type = loader->GetFileType();
- if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error) {
- return;
- }
+void EmulationSession::InitializeGpuDriver(const std::string& hook_lib_dir,
+ const std::string& custom_driver_dir,
+ const std::string& custom_driver_name,
+ const std::string& file_redirect_dir) {
+#ifdef ARCHITECTURE_arm64
+ void* handle{};
+ const char* file_redirect_dir_{};
+ int featureFlags{};
- u64 program_id = 0;
- const auto res2 = loader->ReadProgramId(program_id);
- if (res2 == Loader::ResultStatus::Success && file_type == Loader::FileType::NCA) {
- m_manual_provider->AddEntry(FileSys::TitleType::Application,
- FileSys::GetCRTypeFromNCAType(FileSys::NCA{file}.GetType()),
- program_id, file);
- } else if (res2 == Loader::ResultStatus::Success &&
- (file_type == Loader::FileType::XCI || file_type == Loader::FileType::NSP)) {
- const auto nsp = file_type == Loader::FileType::NSP
- ? std::make_shared<FileSys::NSP>(file)
- : FileSys::XCI{file}.GetSecurePartitionNSP();
- for (const auto& title : nsp->GetNCAs()) {
- for (const auto& entry : title.second) {
- m_manual_provider->AddEntry(entry.first.first, entry.first.second, title.first,
- entry.second->GetBaseFile());
- }
- }
- }
+ // Enable driver file redirection when renderer debugging is enabled.
+ if (Settings::values.renderer_debug && file_redirect_dir.size()) {
+ featureFlags |= ADRENOTOOLS_DRIVER_FILE_REDIRECT;
+ file_redirect_dir_ = file_redirect_dir.c_str();
}
- Core::SystemResultStatus InitializeEmulation(const std::string& filepath) {
- std::scoped_lock lock(m_mutex);
-
- // Create the render window.
- m_window = std::make_unique<EmuWindow_Android>(&m_input_subsystem, m_native_window,
- m_vulkan_library);
-
- m_system.SetFilesystem(m_vfs);
- m_system.GetUserChannel().clear();
-
- // Initialize system.
- jauto android_keyboard = std::make_unique<SoftwareKeyboard::AndroidKeyboard>();
- m_software_keyboard = android_keyboard.get();
- m_system.SetShuttingDown(false);
- m_system.ApplySettings();
- Settings::LogSettings();
- m_system.HIDCore().ReloadInputDevices();
- m_system.SetAppletFrontendSet({
- nullptr, // Amiibo Settings
- nullptr, // Controller Selector
- nullptr, // Error Display
- nullptr, // Mii Editor
- nullptr, // Parental Controls
- nullptr, // Photo Viewer
- nullptr, // Profile Selector
- std::move(android_keyboard), // Software Keyboard
- nullptr, // Web Browser
- });
-
- // Initialize filesystem.
- m_manual_provider = std::make_unique<FileSys::ManualContentProvider>();
- m_system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
- m_system.RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual,
- m_manual_provider.get());
- m_system.GetFileSystemController().CreateFactories(*m_vfs);
- ConfigureFilesystemProvider(filepath);
-
- // Initialize account manager
- m_profile_manager = std::make_unique<Service::Account::ProfileManager>();
-
- // Load the ROM.
- m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath);
- if (m_load_result != Core::SystemResultStatus::Success) {
- return m_load_result;
- }
-
- // Complete initialization.
- m_system.GPU().Start();
- m_system.GetCpuManager().OnGpuReady();
- m_system.RegisterExitCallback([&] { HaltEmulation(); });
+ // Try to load a custom driver.
+ if (custom_driver_name.size()) {
+ handle = adrenotools_open_libvulkan(
+ RTLD_NOW, featureFlags | ADRENOTOOLS_DRIVER_CUSTOM, nullptr, hook_lib_dir.c_str(),
+ custom_driver_dir.c_str(), custom_driver_name.c_str(), file_redirect_dir_, nullptr);
+ }
- return Core::SystemResultStatus::Success;
+ // Try to load the system driver.
+ if (!handle) {
+ handle = adrenotools_open_libvulkan(RTLD_NOW, featureFlags, nullptr, hook_lib_dir.c_str(),
+ nullptr, nullptr, file_redirect_dir_, nullptr);
}
- void ShutdownEmulation() {
- std::scoped_lock lock(m_mutex);
+ m_vulkan_library = std::make_shared<Common::DynamicLibrary>(handle);
+#endif
+}
- m_is_running = false;
+bool EmulationSession::IsRunning() const {
+ return m_is_running;
+}
- // Unload user input.
- m_system.HIDCore().UnloadInputDevices();
+bool EmulationSession::IsPaused() const {
+ return m_is_running && m_is_paused;
+}
- // Shutdown the main emulated process
- if (m_load_result == Core::SystemResultStatus::Success) {
- m_system.DetachDebugger();
- m_system.ShutdownMainProcess();
- m_detached_tasks.WaitForAllTasks();
- m_load_result = Core::SystemResultStatus::ErrorNotInitialized;
- m_window.reset();
- OnEmulationStopped(Core::SystemResultStatus::Success);
- return;
- }
+const Core::PerfStatsResults& EmulationSession::PerfStats() const {
+ std::scoped_lock m_perf_stats_lock(m_perf_stats_mutex);
+ return m_perf_stats;
+}
- // Tear down the render window.
- m_window.reset();
+void EmulationSession::SurfaceChanged() {
+ if (!IsRunning()) {
+ return;
}
+ m_window->OnSurfaceChanged(m_native_window);
+}
- void PauseEmulation() {
- std::scoped_lock lock(m_mutex);
- m_system.Pause();
- m_is_paused = true;
+void EmulationSession::ConfigureFilesystemProvider(const std::string& filepath) {
+ const auto file = m_system.GetFilesystem()->OpenFile(filepath, FileSys::Mode::Read);
+ if (!file) {
+ return;
}
- void UnPauseEmulation() {
- std::scoped_lock lock(m_mutex);
- m_system.Run();
- m_is_paused = false;
+ auto loader = Loader::GetLoader(m_system, file);
+ if (!loader) {
+ return;
}
- void HaltEmulation() {
- std::scoped_lock lock(m_mutex);
- m_is_running = false;
- m_cv.notify_one();
+ const auto file_type = loader->GetFileType();
+ if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error) {
+ return;
}
- void RunEmulation() {
- {
- std::scoped_lock lock(m_mutex);
- m_is_running = true;
+ u64 program_id = 0;
+ const auto res2 = loader->ReadProgramId(program_id);
+ if (res2 == Loader::ResultStatus::Success && file_type == Loader::FileType::NCA) {
+ m_manual_provider->AddEntry(FileSys::TitleType::Application,
+ FileSys::GetCRTypeFromNCAType(FileSys::NCA{file}.GetType()),
+ program_id, file);
+ } else if (res2 == Loader::ResultStatus::Success &&
+ (file_type == Loader::FileType::XCI || file_type == Loader::FileType::NSP)) {
+ const auto nsp = file_type == Loader::FileType::NSP
+ ? std::make_shared<FileSys::NSP>(file)
+ : FileSys::XCI{file}.GetSecurePartitionNSP();
+ for (const auto& title : nsp->GetNCAs()) {
+ for (const auto& entry : title.second) {
+ m_manual_provider->AddEntry(entry.first.first, entry.first.second, title.first,
+ entry.second->GetBaseFile());
+ }
}
+ }
+}
- // Load the disk shader cache.
- if (Settings::values.use_disk_shader_cache.GetValue()) {
- LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
- m_system.Renderer().ReadRasterizer()->LoadDiskResources(
- m_system.GetApplicationProcessProgramID(), std::stop_token{},
- LoadDiskCacheProgress);
- LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
- }
+Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath) {
+ std::scoped_lock lock(m_mutex);
+
+ // Create the render window.
+ m_window =
+ std::make_unique<EmuWindow_Android>(&m_input_subsystem, m_native_window, m_vulkan_library);
+
+ m_system.SetFilesystem(m_vfs);
+ m_system.GetUserChannel().clear();
+
+ // Initialize system.
+ jauto android_keyboard = std::make_unique<SoftwareKeyboard::AndroidKeyboard>();
+ m_software_keyboard = android_keyboard.get();
+ m_system.SetShuttingDown(false);
+ m_system.ApplySettings();
+ Settings::LogSettings();
+ m_system.HIDCore().ReloadInputDevices();
+ m_system.SetAppletFrontendSet({
+ nullptr, // Amiibo Settings
+ nullptr, // Controller Selector
+ nullptr, // Error Display
+ nullptr, // Mii Editor
+ nullptr, // Parental Controls
+ nullptr, // Photo Viewer
+ nullptr, // Profile Selector
+ std::move(android_keyboard), // Software Keyboard
+ nullptr, // Web Browser
+ });
+
+ // Initialize filesystem.
+ m_manual_provider = std::make_unique<FileSys::ManualContentProvider>();
+ m_system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
+ m_system.RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual,
+ m_manual_provider.get());
+ m_system.GetFileSystemController().CreateFactories(*m_vfs);
+ ConfigureFilesystemProvider(filepath);
+
+ // Initialize account manager
+ m_profile_manager = std::make_unique<Service::Account::ProfileManager>();
+
+ // Load the ROM.
+ m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath);
+ if (m_load_result != Core::SystemResultStatus::Success) {
+ return m_load_result;
+ }
+
+ // Complete initialization.
+ m_system.GPU().Start();
+ m_system.GetCpuManager().OnGpuReady();
+ m_system.RegisterExitCallback([&] { HaltEmulation(); });
- void(m_system.Run());
+ return Core::SystemResultStatus::Success;
+}
- if (m_system.DebuggerEnabled()) {
- m_system.InitializeDebugger();
- }
+void EmulationSession::ShutdownEmulation() {
+ std::scoped_lock lock(m_mutex);
- OnEmulationStarted();
+ m_is_running = false;
- while (true) {
- {
- [[maybe_unused]] std::unique_lock lock(m_mutex);
- if (m_cv.wait_for(lock, std::chrono::milliseconds(800),
- [&]() { return !m_is_running; })) {
- // Emulation halted.
- break;
- }
- }
- {
- // Refresh performance stats.
- std::scoped_lock m_perf_stats_lock(m_perf_stats_mutex);
- m_perf_stats = m_system.GetAndResetPerfStats();
- }
- }
- }
-
- std::string GetRomTitle(const std::string& path) {
- return GetRomMetadata(path).title;
- }
-
- std::vector<u8> GetRomIcon(const std::string& path) {
- return GetRomMetadata(path).icon;
- }
+ // Unload user input.
+ m_system.HIDCore().UnloadInputDevices();
- bool GetIsHomebrew(const std::string& path) {
- return GetRomMetadata(path).isHomebrew;
+ // Shutdown the main emulated process
+ if (m_load_result == Core::SystemResultStatus::Success) {
+ m_system.DetachDebugger();
+ m_system.ShutdownMainProcess();
+ m_detached_tasks.WaitForAllTasks();
+ m_load_result = Core::SystemResultStatus::ErrorNotInitialized;
+ m_window.reset();
+ OnEmulationStopped(Core::SystemResultStatus::Success);
+ return;
}
- void ResetRomMetadata() {
- m_rom_metadata_cache.clear();
- }
+ // Tear down the render window.
+ m_window.reset();
+}
- bool IsHandheldOnly() {
- jconst npad_style_set = m_system.HIDCore().GetSupportedStyleTag();
+void EmulationSession::PauseEmulation() {
+ std::scoped_lock lock(m_mutex);
+ m_system.Pause();
+ m_is_paused = true;
+}
- if (npad_style_set.fullkey == 1) {
- return false;
- }
+void EmulationSession::UnPauseEmulation() {
+ std::scoped_lock lock(m_mutex);
+ m_system.Run();
+ m_is_paused = false;
+}
- if (npad_style_set.handheld == 0) {
- return false;
- }
+void EmulationSession::HaltEmulation() {
+ std::scoped_lock lock(m_mutex);
+ m_is_running = false;
+ m_cv.notify_one();
+}
- return !Settings::IsDockedMode();
+void EmulationSession::RunEmulation() {
+ {
+ std::scoped_lock lock(m_mutex);
+ m_is_running = true;
}
- void SetDeviceType([[maybe_unused]] int index, int type) {
- jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index);
- controller->SetNpadStyleIndex(static_cast<Core::HID::NpadStyleIndex>(type));
+ // Load the disk shader cache.
+ if (Settings::values.use_disk_shader_cache.GetValue()) {
+ LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
+ m_system.Renderer().ReadRasterizer()->LoadDiskResources(
+ m_system.GetApplicationProcessProgramID(), std::stop_token{}, LoadDiskCacheProgress);
+ LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
}
- void OnGamepadConnectEvent([[maybe_unused]] int index) {
- jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index);
-
- // Ensure that player1 is configured correctly and handheld disconnected
- if (controller->GetNpadIdType() == Core::HID::NpadIdType::Player1) {
- jauto handheld =
- m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
+ void(m_system.Run());
- if (controller->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::Handheld) {
- handheld->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
- controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
- handheld->Disconnect();
- }
- }
+ if (m_system.DebuggerEnabled()) {
+ m_system.InitializeDebugger();
+ }
- // Ensure that handheld is configured correctly and player 1 disconnected
- if (controller->GetNpadIdType() == Core::HID::NpadIdType::Handheld) {
- jauto player1 =
- m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
+ OnEmulationStarted();
- if (controller->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::Handheld) {
- player1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
- controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
- player1->Disconnect();
+ while (true) {
+ {
+ [[maybe_unused]] std::unique_lock lock(m_mutex);
+ if (m_cv.wait_for(lock, std::chrono::milliseconds(800),
+ [&]() { return !m_is_running; })) {
+ // Emulation halted.
+ break;
}
}
-
- if (!controller->IsConnected()) {
- controller->Connect();
+ {
+ // Refresh performance stats.
+ std::scoped_lock m_perf_stats_lock(m_perf_stats_mutex);
+ m_perf_stats = m_system.GetAndResetPerfStats();
}
}
+}
+
+bool EmulationSession::IsHandheldOnly() {
+ jconst npad_style_set = m_system.HIDCore().GetSupportedStyleTag();
- void OnGamepadDisconnectEvent([[maybe_unused]] int index) {
- jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index);
- controller->Disconnect();
+ if (npad_style_set.fullkey == 1) {
+ return false;
}
- SoftwareKeyboard::AndroidKeyboard* SoftwareKeyboard() {
- return m_software_keyboard;
+ if (npad_style_set.handheld == 0) {
+ return false;
}
-private:
- struct RomMetadata {
- std::string title;
- std::vector<u8> icon;
- bool isHomebrew;
- };
+ return !Settings::IsDockedMode();
+}
- RomMetadata GetRomMetadata(const std::string& path) {
- if (jauto search = m_rom_metadata_cache.find(path); search != m_rom_metadata_cache.end()) {
- return search->second;
- }
+void EmulationSession::SetDeviceType([[maybe_unused]] int index, int type) {
+ jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index);
+ controller->SetNpadStyleIndex(static_cast<Core::HID::NpadStyleIndex>(type));
+}
- return CacheRomMetadata(path);
- }
+void EmulationSession::OnGamepadConnectEvent([[maybe_unused]] int index) {
+ jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index);
- RomMetadata CacheRomMetadata(const std::string& path) {
- jconst file = Core::GetGameFileFromPath(m_vfs, path);
- jauto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0);
+ // Ensure that player1 is configured correctly and handheld disconnected
+ if (controller->GetNpadIdType() == Core::HID::NpadIdType::Player1) {
+ jauto handheld = m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
- RomMetadata entry;
- loader->ReadTitle(entry.title);
- loader->ReadIcon(entry.icon);
- if (loader->GetFileType() == Loader::FileType::NRO) {
- jauto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get());
- entry.isHomebrew = loader_nro->IsHomebrew();
- } else {
- entry.isHomebrew = false;
+ if (controller->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::Handheld) {
+ handheld->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
+ controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
+ handheld->Disconnect();
}
-
- m_rom_metadata_cache[path] = entry;
-
- return entry;
}
-private:
- static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max) {
- JNIEnv* env = IDCache::GetEnvForThread();
- env->CallStaticVoidMethod(IDCache::GetDiskCacheProgressClass(),
- IDCache::GetDiskCacheLoadProgress(), static_cast<jint>(stage),
- static_cast<jint>(progress), static_cast<jint>(max));
- }
+ // Ensure that handheld is configured correctly and player 1 disconnected
+ if (controller->GetNpadIdType() == Core::HID::NpadIdType::Handheld) {
+ jauto player1 = m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
- static void OnEmulationStarted() {
- JNIEnv* env = IDCache::GetEnvForThread();
- env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
- IDCache::GetOnEmulationStarted());
+ if (controller->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::Handheld) {
+ player1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
+ controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
+ player1->Disconnect();
+ }
}
- static void OnEmulationStopped(Core::SystemResultStatus result) {
- JNIEnv* env = IDCache::GetEnvForThread();
- env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
- IDCache::GetOnEmulationStopped(), static_cast<jint>(result));
+ if (!controller->IsConnected()) {
+ controller->Connect();
}
+}
-private:
- static EmulationSession s_instance;
-
- // Frontend management
- std::unordered_map<std::string, RomMetadata> m_rom_metadata_cache;
-
- // Window management
- std::unique_ptr<EmuWindow_Android> m_window;
- ANativeWindow* m_native_window{};
-
- // Core emulation
- Core::System m_system;
- InputCommon::InputSubsystem m_input_subsystem;
- Common::DetachedTasks m_detached_tasks;
- Core::PerfStatsResults m_perf_stats{};
- std::shared_ptr<FileSys::VfsFilesystem> m_vfs;
- Core::SystemResultStatus m_load_result{Core::SystemResultStatus::ErrorNotInitialized};
- std::atomic<bool> m_is_running = false;
- std::atomic<bool> m_is_paused = false;
- SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
- std::unique_ptr<Service::Account::ProfileManager> m_profile_manager;
- std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
+void EmulationSession::OnGamepadDisconnectEvent([[maybe_unused]] int index) {
+ jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index);
+ controller->Disconnect();
+}
- // GPU driver parameters
- std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;
+SoftwareKeyboard::AndroidKeyboard* EmulationSession::SoftwareKeyboard() {
+ return m_software_keyboard;
+}
- // Synchronization
- std::condition_variable_any m_cv;
- mutable std::mutex m_perf_stats_mutex;
- mutable std::mutex m_mutex;
-};
+void EmulationSession::LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress,
+ int max) {
+ JNIEnv* env = IDCache::GetEnvForThread();
+ env->CallStaticVoidMethod(IDCache::GetDiskCacheProgressClass(),
+ IDCache::GetDiskCacheLoadProgress(), static_cast<jint>(stage),
+ static_cast<jint>(progress), static_cast<jint>(max));
+}
-/*static*/ EmulationSession EmulationSession::s_instance;
+void EmulationSession::OnEmulationStarted() {
+ JNIEnv* env = IDCache::GetEnvForThread();
+ env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnEmulationStarted());
+}
-} // Anonymous namespace
+void EmulationSession::OnEmulationStopped(Core::SystemResultStatus result) {
+ JNIEnv* env = IDCache::GetEnvForThread();
+ env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnEmulationStopped(),
+ static_cast<jint>(result));
+}
static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
Common::Log::Initialize();
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h
new file mode 100644
index 000000000..2eb5c4349
--- /dev/null
+++ b/src/android/app/src/main/jni/native.h
@@ -0,0 +1,84 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <android/native_window_jni.h>
+#include "core/core.h"
+#include "core/perf_stats.h"
+#include "jni/emu_window/emu_window.h"
+#include "jni/applets/software_keyboard.h"
+#include "video_core/rasterizer_interface.h"
+#include "common/detached_tasks.h"
+#include "core/hle/service/acc/profile_manager.h"
+#include "core/file_sys/registered_cache.h"
+
+#pragma once
+
+class EmulationSession final {
+public:
+ explicit EmulationSession();
+ ~EmulationSession() = default;
+
+ static EmulationSession& GetInstance();
+ const Core::System& System() const;
+ Core::System& System();
+
+ const EmuWindow_Android& Window() const;
+ EmuWindow_Android& Window();
+ ANativeWindow* NativeWindow() const;
+ void SetNativeWindow(ANativeWindow* native_window);
+ void SurfaceChanged();
+
+ int InstallFileToNand(std::string filename, std::string file_extension);
+ void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir,
+ const std::string& custom_driver_name,
+ const std::string& file_redirect_dir);
+
+ bool IsRunning() const;
+ bool IsPaused() const;
+ void PauseEmulation();
+ void UnPauseEmulation();
+ void HaltEmulation();
+ void RunEmulation();
+ void ShutdownEmulation();
+
+ const Core::PerfStatsResults& PerfStats() const;
+ void ConfigureFilesystemProvider(const std::string& filepath);
+ Core::SystemResultStatus InitializeEmulation(const std::string& filepath);
+
+ bool IsHandheldOnly();
+ void SetDeviceType([[maybe_unused]] int index, int type);
+ void OnGamepadConnectEvent([[maybe_unused]] int index);
+ void OnGamepadDisconnectEvent([[maybe_unused]] int index);
+ SoftwareKeyboard::AndroidKeyboard* SoftwareKeyboard();
+
+private:
+ static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
+ static void OnEmulationStarted();
+ static void OnEmulationStopped(Core::SystemResultStatus result);
+
+private:
+ // Window management
+ std::unique_ptr<EmuWindow_Android> m_window;
+ ANativeWindow* m_native_window{};
+
+ // Core emulation
+ Core::System m_system;
+ InputCommon::InputSubsystem m_input_subsystem;
+ Common::DetachedTasks m_detached_tasks;
+ Core::PerfStatsResults m_perf_stats{};
+ std::shared_ptr<FileSys::VfsFilesystem> m_vfs;
+ Core::SystemResultStatus m_load_result{Core::SystemResultStatus::ErrorNotInitialized};
+ std::atomic<bool> m_is_running = false;
+ std::atomic<bool> m_is_paused = false;
+ SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
+ std::unique_ptr<Service::Account::ProfileManager> m_profile_manager;
+ std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
+
+ // GPU driver parameters
+ std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;
+
+ // Synchronization
+ std::condition_variable_any m_cv;
+ mutable std::mutex m_perf_stats_mutex;
+ mutable std::mutex m_mutex;
+};