diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt deleted file mode 100644 index b0a750c..0000000 --- a/src/android/app/src/main/jni/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# SPDX-FileCopyrightText: 2023 sudachi Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later - -add_library(sudachi-android SHARED - emu_window/emu_window.cpp - emu_window/emu_window.h - native.cpp - native.h - native_config.cpp - android_settings.cpp - game_metadata.cpp - native_log.cpp - android_config.cpp - android_config.h - native_input.cpp -) - -set_property(TARGET sudachi-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) - -target_link_libraries(sudachi-android PRIVATE audio_core common core input_common frontend_common Vulkan::Headers) -target_link_libraries(sudachi-android PRIVATE android camera2ndk EGL glad jnigraphics log) -if (ARCHITECTURE_arm64) - target_link_libraries(sudachi-android PRIVATE adrenotools) -endif() - -set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} sudachi-android) diff --git a/src/android/app/src/main/jni/android_common/android_common.cpp b/src/android/app/src/main/jni/android_common/android_common.cpp deleted file mode 100644 index b06d73c..0000000 --- a/src/android/app/src/main/jni/android_common/android_common.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 sudachi Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "jni/android_common/android_common.h" - -#include -#include - -#include - -#include "common/string_util.h" -#include "jni/id_cache.h" - -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(jchars), length); - const std::string converted_string = Common::UTF16ToUTF8(string_view); - env->ReleaseStringChars(jstr, jchars); - - return converted_string; -} - -jstring ToJString(JNIEnv* env, std::string_view str) { - const std::u16string converted_string = Common::UTF8ToUTF16(str); - return env->NewString(reinterpret_cast(converted_string.data()), - static_cast(converted_string.size())); -} - -jstring ToJString(JNIEnv* env, std::u16string_view str) { - return ToJString(env, Common::UTF16ToUTF8(str)); -} - -double GetJDouble(JNIEnv* env, jobject jdouble) { - return env->GetDoubleField(jdouble, IDCache::GetDoubleValueField()); -} - -jobject ToJDouble(JNIEnv* env, double value) { - return env->NewObject(IDCache::GetDoubleClass(), IDCache::GetDoubleConstructor(), value); -} - -s32 GetJInteger(JNIEnv* env, jobject jinteger) { - return env->GetIntField(jinteger, IDCache::GetIntegerValueField()); -} - -jobject ToJInteger(JNIEnv* env, s32 value) { - return env->NewObject(IDCache::GetIntegerClass(), IDCache::GetIntegerConstructor(), value); -} - -bool GetJBoolean(JNIEnv* env, jobject jboolean) { - return env->GetBooleanField(jboolean, IDCache::GetBooleanValueField()); -} - -jobject ToJBoolean(JNIEnv* env, bool value) { - return env->NewObject(IDCache::GetBooleanClass(), IDCache::GetBooleanConstructor(), value); -} diff --git a/src/android/app/src/main/jni/android_common/android_common.h b/src/android/app/src/main/jni/android_common/android_common.h deleted file mode 100644 index 5fd1c05..0000000 --- a/src/android/app/src/main/jni/android_common/android_common.h +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 sudachi Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include - -#include -#include "common/common_types.h" - -std::string GetJString(JNIEnv* env, jstring jstr); -jstring ToJString(JNIEnv* env, std::string_view str); -jstring ToJString(JNIEnv* env, std::u16string_view str); - -double GetJDouble(JNIEnv* env, jobject jdouble); -jobject ToJDouble(JNIEnv* env, double value); - -s32 GetJInteger(JNIEnv* env, jobject jinteger); -jobject ToJInteger(JNIEnv* env, s32 value); - -bool GetJBoolean(JNIEnv* env, jobject jboolean); -jobject ToJBoolean(JNIEnv* env, bool value); diff --git a/src/android/app/src/main/jni/applets/software_keyboard.cpp b/src/android/app/src/main/jni/applets/software_keyboard.cpp deleted file mode 100644 index 4a02bc6..0000000 --- a/src/android/app/src/main/jni/applets/software_keyboard.cpp +++ /dev/null @@ -1,277 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 sudachi Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include - -#include - -#include "common/logging/log.h" -#include "common/string_util.h" -#include "core/core.h" -#include "jni/android_common/android_common.h" -#include "jni/applets/software_keyboard.h" -#include "jni/id_cache.h" - -static jclass s_software_keyboard_class; -static jclass s_keyboard_config_class; -static jclass s_keyboard_data_class; -static jmethodID s_swkbd_execute_normal; -static jmethodID s_swkbd_execute_inline; - -namespace SoftwareKeyboard { - -static jobject ToJKeyboardParams(const Core::Frontend::KeyboardInitializeParameters& config) { - JNIEnv* env = IDCache::GetEnvForThread(); - jobject object = env->AllocObject(s_keyboard_config_class); - - env->SetObjectField(object, - env->GetFieldID(s_keyboard_config_class, "ok_text", "Ljava/lang/String;"), - ToJString(env, config.ok_text)); - env->SetObjectField( - object, env->GetFieldID(s_keyboard_config_class, "header_text", "Ljava/lang/String;"), - ToJString(env, config.header_text)); - env->SetObjectField(object, - env->GetFieldID(s_keyboard_config_class, "sub_text", "Ljava/lang/String;"), - ToJString(env, config.sub_text)); - env->SetObjectField( - object, env->GetFieldID(s_keyboard_config_class, "guide_text", "Ljava/lang/String;"), - ToJString(env, config.guide_text)); - env->SetObjectField( - object, env->GetFieldID(s_keyboard_config_class, "initial_text", "Ljava/lang/String;"), - ToJString(env, config.initial_text)); - env->SetShortField(object, - env->GetFieldID(s_keyboard_config_class, "left_optional_symbol_key", "S"), - static_cast(config.left_optional_symbol_key)); - env->SetShortField(object, - env->GetFieldID(s_keyboard_config_class, "right_optional_symbol_key", "S"), - static_cast(config.right_optional_symbol_key)); - env->SetIntField(object, env->GetFieldID(s_keyboard_config_class, "max_text_length", "I"), - static_cast(config.max_text_length)); - env->SetIntField(object, env->GetFieldID(s_keyboard_config_class, "min_text_length", "I"), - static_cast(config.min_text_length)); - env->SetIntField(object, - env->GetFieldID(s_keyboard_config_class, "initial_cursor_position", "I"), - static_cast(config.initial_cursor_position)); - env->SetIntField(object, env->GetFieldID(s_keyboard_config_class, "type", "I"), - static_cast(config.type)); - env->SetIntField(object, env->GetFieldID(s_keyboard_config_class, "password_mode", "I"), - static_cast(config.password_mode)); - env->SetIntField(object, env->GetFieldID(s_keyboard_config_class, "text_draw_type", "I"), - static_cast(config.text_draw_type)); - env->SetIntField(object, env->GetFieldID(s_keyboard_config_class, "key_disable_flags", "I"), - static_cast(config.key_disable_flags.raw)); - env->SetBooleanField(object, - env->GetFieldID(s_keyboard_config_class, "use_blur_background", "Z"), - static_cast(config.use_blur_background)); - env->SetBooleanField(object, - env->GetFieldID(s_keyboard_config_class, "enable_backspace_button", "Z"), - static_cast(config.enable_backspace_button)); - env->SetBooleanField(object, - env->GetFieldID(s_keyboard_config_class, "enable_return_button", "Z"), - static_cast(config.enable_return_button)); - env->SetBooleanField(object, - env->GetFieldID(s_keyboard_config_class, "disable_cancel_button", "Z"), - static_cast(config.disable_cancel_button)); - - return object; -} - -AndroidKeyboard::ResultData AndroidKeyboard::ResultData::CreateFromFrontend(jobject object) { - JNIEnv* env = IDCache::GetEnvForThread(); - const jstring string = reinterpret_cast(env->GetObjectField( - object, env->GetFieldID(s_keyboard_data_class, "text", "Ljava/lang/String;"))); - return ResultData{GetJString(env, string), - static_cast(env->GetIntField( - object, env->GetFieldID(s_keyboard_data_class, "result", "I")))}; -} - -AndroidKeyboard::~AndroidKeyboard() = default; - -void AndroidKeyboard::InitializeKeyboard( - bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, - SubmitNormalCallback submit_normal_callback_, SubmitInlineCallback submit_inline_callback_) { - if (is_inline) { - LOG_WARNING( - Frontend, - "(STUBBED) called, backend requested to initialize the inline software keyboard."); - - submit_inline_callback = std::move(submit_inline_callback_); - } else { - LOG_WARNING( - Frontend, - "(STUBBED) called, backend requested to initialize the normal software keyboard."); - - submit_normal_callback = std::move(submit_normal_callback_); - } - - parameters = std::move(initialize_parameters); - - LOG_INFO(Frontend, - "\nKeyboardInitializeParameters:" - "\nok_text={}" - "\nheader_text={}" - "\nsub_text={}" - "\nguide_text={}" - "\ninitial_text={}" - "\nmax_text_length={}" - "\nmin_text_length={}" - "\ninitial_cursor_position={}" - "\ntype={}" - "\npassword_mode={}" - "\ntext_draw_type={}" - "\nkey_disable_flags={}" - "\nuse_blur_background={}" - "\nenable_backspace_button={}" - "\nenable_return_button={}" - "\ndisable_cancel_button={}", - Common::UTF16ToUTF8(parameters.ok_text), Common::UTF16ToUTF8(parameters.header_text), - Common::UTF16ToUTF8(parameters.sub_text), Common::UTF16ToUTF8(parameters.guide_text), - Common::UTF16ToUTF8(parameters.initial_text), parameters.max_text_length, - parameters.min_text_length, parameters.initial_cursor_position, parameters.type, - parameters.password_mode, parameters.text_draw_type, parameters.key_disable_flags.raw, - parameters.use_blur_background, parameters.enable_backspace_button, - parameters.enable_return_button, parameters.disable_cancel_button); -} - -void AndroidKeyboard::ShowNormalKeyboard() const { - LOG_DEBUG(Frontend, "called, backend requested to show the normal software keyboard."); - - ResultData data{}; - - // Pivot to a new thread, as we cannot call GetEnvForThread() from a Fiber. - std::thread([&] { - data = ResultData::CreateFromFrontend(IDCache::GetEnvForThread()->CallStaticObjectMethod( - s_software_keyboard_class, s_swkbd_execute_normal, ToJKeyboardParams(parameters))); - }).join(); - - SubmitNormalText(data); -} - -void AndroidKeyboard::ShowTextCheckDialog( - Service::AM::Frontend::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const { - LOG_WARNING(Frontend, "(STUBBED) called, backend requested to show the text check dialog."); -} - -void AndroidKeyboard::ShowInlineKeyboard( - Core::Frontend::InlineAppearParameters appear_parameters) const { - LOG_WARNING(Frontend, - "(STUBBED) called, backend requested to show the inline software keyboard."); - - LOG_INFO(Frontend, - "\nInlineAppearParameters:" - "\nmax_text_length={}" - "\nmin_text_length={}" - "\nkey_top_scale_x={}" - "\nkey_top_scale_y={}" - "\nkey_top_translate_x={}" - "\nkey_top_translate_y={}" - "\ntype={}" - "\nkey_disable_flags={}" - "\nkey_top_as_floating={}" - "\nenable_backspace_button={}" - "\nenable_return_button={}" - "\ndisable_cancel_button={}", - appear_parameters.max_text_length, appear_parameters.min_text_length, - appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y, - appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y, - appear_parameters.type, appear_parameters.key_disable_flags.raw, - appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button, - appear_parameters.enable_return_button, appear_parameters.disable_cancel_button); - - // Pivot to a new thread, as we cannot call GetEnvForThread() from a Fiber. - m_is_inline_active = true; - std::thread([&] { - IDCache::GetEnvForThread()->CallStaticVoidMethod( - s_software_keyboard_class, s_swkbd_execute_inline, ToJKeyboardParams(parameters)); - }).join(); -} - -void AndroidKeyboard::HideInlineKeyboard() const { - LOG_WARNING(Frontend, - "(STUBBED) called, backend requested to hide the inline software keyboard."); -} - -void AndroidKeyboard::InlineTextChanged( - Core::Frontend::InlineTextParameters text_parameters) const { - LOG_WARNING(Frontend, - "(STUBBED) called, backend requested to change the inline keyboard text."); - - LOG_INFO(Frontend, - "\nInlineTextParameters:" - "\ninput_text={}" - "\ncursor_position={}", - Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position); - - submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, - text_parameters.input_text, text_parameters.cursor_position); -} - -void AndroidKeyboard::ExitKeyboard() const { - LOG_WARNING(Frontend, "(STUBBED) called, backend requested to exit the software keyboard."); -} - -void AndroidKeyboard::SubmitInlineKeyboardText(std::u16string submitted_text) { - if (!m_is_inline_active) { - return; - } - - m_current_text += submitted_text; - - submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text, - m_current_text.size()); -} - -void AndroidKeyboard::SubmitInlineKeyboardInput(int key_code) { - static constexpr int KEYCODE_BACK = 4; - static constexpr int KEYCODE_ENTER = 66; - static constexpr int KEYCODE_DEL = 67; - - if (!m_is_inline_active) { - return; - } - - switch (key_code) { - case KEYCODE_BACK: - case KEYCODE_ENTER: - m_is_inline_active = false; - submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::DecidedEnter, m_current_text, - static_cast(m_current_text.size())); - break; - case KEYCODE_DEL: - m_current_text.pop_back(); - submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text, - m_current_text.size()); - break; - } -} - -void AndroidKeyboard::SubmitNormalText(const ResultData& data) const { - submit_normal_callback(data.result, Common::UTF8ToUTF16(data.text), true); -} - -void InitJNI(JNIEnv* env) { - s_software_keyboard_class = reinterpret_cast( - env->NewGlobalRef(env->FindClass("org/sudachi/sudachi_emu/applets/keyboard/SoftwareKeyboard"))); - s_keyboard_config_class = reinterpret_cast(env->NewGlobalRef( - env->FindClass("org/sudachi/sudachi_emu/applets/keyboard/SoftwareKeyboard$KeyboardConfig"))); - s_keyboard_data_class = reinterpret_cast(env->NewGlobalRef( - env->FindClass("org/sudachi/sudachi_emu/applets/keyboard/SoftwareKeyboard$KeyboardData"))); - - s_swkbd_execute_normal = env->GetStaticMethodID( - s_software_keyboard_class, "executeNormal", - "(Lorg/sudachi/sudachi_emu/applets/keyboard/SoftwareKeyboard$KeyboardConfig;)Lorg/sudachi/sudachi_emu/" - "applets/keyboard/SoftwareKeyboard$KeyboardData;"); - s_swkbd_execute_inline = env->GetStaticMethodID( - s_software_keyboard_class, "executeInline", - "(Lorg/sudachi/sudachi_emu/applets/keyboard/SoftwareKeyboard$KeyboardConfig;)V"); -} - -void CleanupJNI(JNIEnv* env) { - env->DeleteGlobalRef(s_software_keyboard_class); - env->DeleteGlobalRef(s_keyboard_config_class); - env->DeleteGlobalRef(s_keyboard_data_class); -} - -} // namespace SoftwareKeyboard diff --git a/src/android/app/src/main/jni/applets/software_keyboard.h b/src/android/app/src/main/jni/applets/software_keyboard.h deleted file mode 100644 index 13ad350..0000000 --- a/src/android/app/src/main/jni/applets/software_keyboard.h +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 sudachi Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include - -#include "core/frontend/applets/software_keyboard.h" - -namespace SoftwareKeyboard { - -class AndroidKeyboard final : public Core::Frontend::SoftwareKeyboardApplet { -public: - ~AndroidKeyboard() override; - - void Close() const override { - ExitKeyboard(); - } - - void InitializeKeyboard(bool is_inline, - Core::Frontend::KeyboardInitializeParameters initialize_parameters, - SubmitNormalCallback submit_normal_callback_, - SubmitInlineCallback submit_inline_callback_) override; - - void ShowNormalKeyboard() const override; - - void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const override; - - void ShowInlineKeyboard( - Core::Frontend::InlineAppearParameters appear_parameters) const override; - - void HideInlineKeyboard() const override; - - void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const override; - - void ExitKeyboard() const override; - - void SubmitInlineKeyboardText(std::u16string submitted_text); - - void SubmitInlineKeyboardInput(int key_code); - -private: - struct ResultData { - static ResultData CreateFromFrontend(jobject object); - - std::string text; - Service::AM::Frontend::SwkbdResult result{}; - }; - - void SubmitNormalText(const ResultData& result) const; - - Core::Frontend::KeyboardInitializeParameters parameters{}; - - mutable SubmitNormalCallback submit_normal_callback; - mutable SubmitInlineCallback submit_inline_callback; - -private: - mutable bool m_is_inline_active{}; - std::u16string m_current_text; -}; - -// Should be called in JNI_Load -void InitJNI(JNIEnv* env); - -// Should be called in JNI_Unload -void CleanupJNI(JNIEnv* env); - -} // namespace SoftwareKeyboard - -// Native function calls -extern "C" { -JNIEXPORT jobject JNICALL Java_org_citra_citra_1emu_applets_SoftwareKeyboard_ValidateFilters( - JNIEnv* env, jclass clazz, jstring text); - -JNIEXPORT jobject JNICALL Java_org_citra_citra_1emu_applets_SoftwareKeyboard_ValidateInput( - JNIEnv* env, jclass clazz, jstring text); -} diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp deleted file mode 100644 index 694114d..0000000 --- a/src/android/app/src/main/jni/config.cpp +++ /dev/null @@ -1,330 +0,0 @@ -// SPDX-FileCopyrightText: 2023 sudachi Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include - -#include -#include "common/fs/file.h" -#include "common/fs/fs.h" -#include "common/fs/path_util.h" -#include "common/logging/log.h" -#include "common/settings.h" -#include "common/settings_enums.h" -#include "core/hle/service/acc/profile_manager.h" -#include "input_common/main.h" -#include "jni/config.h" -#include "jni/default_ini.h" -#include "uisettings.h" - -namespace FS = Common::FS; - -Config::Config(const std::string& config_name, ConfigType config_type) - : type(config_type), global{config_type == ConfigType::GlobalConfig} { - Initialize(config_name); -} - -Config::~Config() = default; - -bool Config::LoadINI(const std::string& default_contents, bool retry) { - void(FS::CreateParentDir(config_loc)); - config = std::make_unique(FS::PathToUTF8String(config_loc)); - const auto config_loc_str = FS::PathToUTF8String(config_loc); - if (config->ParseError() < 0) { - if (retry) { - LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...", - config_loc_str); - - void(FS::CreateParentDir(config_loc)); - void(FS::WriteStringToFile(config_loc, FS::FileType::TextFile, default_contents)); - - config = std::make_unique(config_loc_str); - - return LoadINI(default_contents, false); - } - LOG_ERROR(Config, "Failed."); - return false; - } - LOG_INFO(Config, "Successfully loaded {}", config_loc_str); - return true; -} - -template <> -void Config::ReadSetting(const std::string& group, Settings::Setting& setting) { - std::string setting_value = config->Get(group, setting.GetLabel(), setting.GetDefault()); - if (setting_value.empty()) { - setting_value = setting.GetDefault(); - } - setting = std::move(setting_value); -} - -template <> -void Config::ReadSetting(const std::string& group, Settings::Setting& setting) { - setting = config->GetBoolean(group, setting.GetLabel(), setting.GetDefault()); -} - -template -void Config::ReadSetting(const std::string& group, Settings::Setting& setting) { - setting = static_cast( - config->GetInteger(group, setting.GetLabel(), static_cast(setting.GetDefault()))); -} - -void Config::ReadValues() { - ReadSetting("ControlsGeneral", Settings::values.mouse_enabled); - ReadSetting("ControlsGeneral", Settings::values.touch_device); - ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled); - ReadSetting("ControlsGeneral", Settings::values.debug_pad_enabled); - ReadSetting("ControlsGeneral", Settings::values.vibration_enabled); - ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations); - ReadSetting("ControlsGeneral", Settings::values.motion_enabled); - Settings::values.touchscreen.enabled = - config->GetBoolean("ControlsGeneral", "touch_enabled", true); - Settings::values.touchscreen.rotation_angle = - config->GetInteger("ControlsGeneral", "touch_angle", 0); - Settings::values.touchscreen.diameter_x = - config->GetInteger("ControlsGeneral", "touch_diameter_x", 15); - Settings::values.touchscreen.diameter_y = - config->GetInteger("ControlsGeneral", "touch_diameter_y", 15); - - int num_touch_from_button_maps = - config->GetInteger("ControlsGeneral", "touch_from_button_map", 0); - if (num_touch_from_button_maps > 0) { - for (int i = 0; i < num_touch_from_button_maps; ++i) { - Settings::TouchFromButtonMap map; - map.name = config->Get("ControlsGeneral", - std::string("touch_from_button_maps_") + std::to_string(i) + - std::string("_name"), - "default"); - const int num_touch_maps = config->GetInteger( - "ControlsGeneral", - std::string("touch_from_button_maps_") + std::to_string(i) + std::string("_count"), - 0); - map.buttons.reserve(num_touch_maps); - - for (int j = 0; j < num_touch_maps; ++j) { - std::string touch_mapping = - config->Get("ControlsGeneral", - std::string("touch_from_button_maps_") + std::to_string(i) + - std::string("_bind_") + std::to_string(j), - ""); - map.buttons.emplace_back(std::move(touch_mapping)); - } - - Settings::values.touch_from_button_maps.emplace_back(std::move(map)); - } - } else { - Settings::values.touch_from_button_maps.emplace_back( - Settings::TouchFromButtonMap{"default", {}}); - num_touch_from_button_maps = 1; - } - Settings::values.touch_from_button_map_index = std::clamp( - Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); - - ReadSetting("ControlsGeneral", Settings::values.udp_input_servers); - - // Data Storage - ReadSetting("Data Storage", Settings::values.use_virtual_sd); - FS::SetSudachiPath(FS::SudachiPath::NANDDir, - config->Get("Data Storage", "nand_directory", - FS::GetSudachiPathString(FS::SudachiPath::NANDDir))); - FS::SetSudachiPath(FS::SudachiPath::SDMCDir, - config->Get("Data Storage", "sdmc_directory", - FS::GetSudachiPathString(FS::SudachiPath::SDMCDir))); - FS::SetSudachiPath(FS::SudachiPath::LoadDir, - config->Get("Data Storage", "load_directory", - FS::GetSudachiPathString(FS::SudachiPath::LoadDir))); - FS::SetSudachiPath(FS::SudachiPath::DumpDir, - config->Get("Data Storage", "dump_directory", - FS::GetSudachiPathString(FS::SudachiPath::DumpDir))); - ReadSetting("Data Storage", Settings::values.gamecard_inserted); - ReadSetting("Data Storage", Settings::values.gamecard_current_game); - ReadSetting("Data Storage", Settings::values.gamecard_path); - - // System - ReadSetting("System", Settings::values.current_user); - Settings::values.current_user = std::clamp(Settings::values.current_user.GetValue(), 0, - Service::Account::MAX_USERS - 1); - - // Disable docked mode by default on Android - Settings::values.use_docked_mode.SetValue(config->GetBoolean("System", "use_docked_mode", false) - ? Settings::ConsoleMode::Docked - : Settings::ConsoleMode::Handheld); - - const auto rng_seed_enabled = config->GetBoolean("System", "rng_seed_enabled", false); - if (rng_seed_enabled) { - Settings::values.rng_seed.SetValue(config->GetInteger("System", "rng_seed", 0)); - } else { - Settings::values.rng_seed.SetValue(0); - } - Settings::values.rng_seed_enabled.SetValue(rng_seed_enabled); - - const auto custom_rtc_enabled = config->GetBoolean("System", "custom_rtc_enabled", false); - if (custom_rtc_enabled) { - Settings::values.custom_rtc = config->GetInteger("System", "custom_rtc", 0); - } else { - Settings::values.custom_rtc = 0; - } - Settings::values.custom_rtc_enabled = custom_rtc_enabled; - - ReadSetting("System", Settings::values.language_index); - ReadSetting("System", Settings::values.region_index); - ReadSetting("System", Settings::values.time_zone_index); - ReadSetting("System", Settings::values.sound_index); - - // Core - ReadSetting("Core", Settings::values.use_multi_core); - ReadSetting("Core", Settings::values.memory_layout_mode); - - // Cpu - ReadSetting("Cpu", Settings::values.cpu_accuracy); - ReadSetting("Cpu", Settings::values.cpu_debug_mode); - ReadSetting("Cpu", Settings::values.cpuopt_page_tables); - ReadSetting("Cpu", Settings::values.cpuopt_block_linking); - ReadSetting("Cpu", Settings::values.cpuopt_return_stack_buffer); - ReadSetting("Cpu", Settings::values.cpuopt_fast_dispatcher); - ReadSetting("Cpu", Settings::values.cpuopt_context_elimination); - ReadSetting("Cpu", Settings::values.cpuopt_const_prop); - ReadSetting("Cpu", Settings::values.cpuopt_misc_ir); - ReadSetting("Cpu", Settings::values.cpuopt_reduce_misalign_checks); - ReadSetting("Cpu", Settings::values.cpuopt_fastmem); - ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives); - ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives); - ReadSetting("Cpu", Settings::values.cpuopt_ignore_memory_aborts); - ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma); - ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error); - ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr); - ReadSetting("Cpu", Settings::values.cpuopt_unsafe_inaccurate_nan); - ReadSetting("Cpu", Settings::values.cpuopt_unsafe_fastmem_check); - ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_global_monitor); - - // Renderer - ReadSetting("Renderer", Settings::values.renderer_backend); - ReadSetting("Renderer", Settings::values.renderer_debug); - ReadSetting("Renderer", Settings::values.renderer_shader_feedback); - ReadSetting("Renderer", Settings::values.enable_nsight_aftermath); - ReadSetting("Renderer", Settings::values.disable_shader_loop_safety_checks); - ReadSetting("Renderer", Settings::values.vulkan_device); - - ReadSetting("Renderer", Settings::values.resolution_setup); - ReadSetting("Renderer", Settings::values.scaling_filter); - ReadSetting("Renderer", Settings::values.fsr_sharpening_slider); - ReadSetting("Renderer", Settings::values.anti_aliasing); - ReadSetting("Renderer", Settings::values.fullscreen_mode); - ReadSetting("Renderer", Settings::values.aspect_ratio); - ReadSetting("Renderer", Settings::values.max_anisotropy); - ReadSetting("Renderer", Settings::values.use_speed_limit); - ReadSetting("Renderer", Settings::values.speed_limit); - ReadSetting("Renderer", Settings::values.use_disk_shader_cache); - ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation); - ReadSetting("Renderer", Settings::values.vsync_mode); - ReadSetting("Renderer", Settings::values.shader_backend); - ReadSetting("Renderer", Settings::values.use_asynchronous_shaders); - ReadSetting("Renderer", Settings::values.nvdec_emulation); - ReadSetting("Renderer", Settings::values.use_fast_gpu_time); - ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); - - ReadSetting("Renderer", Settings::values.bg_red); - ReadSetting("Renderer", Settings::values.bg_green); - ReadSetting("Renderer", Settings::values.bg_blue); - - // Use GPU accuracy normal by default on Android - Settings::values.gpu_accuracy = static_cast(config->GetInteger( - "Renderer", "gpu_accuracy", static_cast(Settings::GpuAccuracy::Normal))); - - // Use GPU default anisotropic filtering on Android - Settings::values.max_anisotropy = - static_cast(config->GetInteger("Renderer", "max_anisotropy", 1)); - - // Disable ASTC compute by default on Android - Settings::values.accelerate_astc.SetValue( - config->GetBoolean("Renderer", "accelerate_astc", false) ? Settings::AstcDecodeMode::Gpu - : Settings::AstcDecodeMode::Cpu); - - // Enable asynchronous presentation by default on Android - Settings::values.async_presentation = - config->GetBoolean("Renderer", "async_presentation", true); - - // Disable force_max_clock by default on Android - Settings::values.renderer_force_max_clock = - config->GetBoolean("Renderer", "force_max_clock", false); - - // Disable use_reactive_flushing by default on Android - Settings::values.use_reactive_flushing = - config->GetBoolean("Renderer", "use_reactive_flushing", false); - - // Audio - ReadSetting("Audio", Settings::values.sink_id); - ReadSetting("Audio", Settings::values.audio_output_device_id); - ReadSetting("Audio", Settings::values.volume); - - // Miscellaneous - // log_filter has a different default here than from common - Settings::values.log_filter = "*:Info"; - ReadSetting("Miscellaneous", Settings::values.use_dev_keys); - - // Debugging - Settings::values.record_frame_times = - config->GetBoolean("Debugging", "record_frame_times", false); - ReadSetting("Debugging", Settings::values.dump_exefs); - ReadSetting("Debugging", Settings::values.dump_nso); - ReadSetting("Debugging", Settings::values.enable_fs_access_log); - ReadSetting("Debugging", Settings::values.reporting_services); - ReadSetting("Debugging", Settings::values.quest_flag); - ReadSetting("Debugging", Settings::values.use_debug_asserts); - ReadSetting("Debugging", Settings::values.use_auto_stub); - ReadSetting("Debugging", Settings::values.disable_macro_jit); - ReadSetting("Debugging", Settings::values.disable_macro_hle); - ReadSetting("Debugging", Settings::values.use_gdbstub); - ReadSetting("Debugging", Settings::values.gdbstub_port); - - const auto title_list = config->Get("AddOns", "title_ids", ""); - std::stringstream ss(title_list); - std::string line; - while (std::getline(ss, line, '|')) { - const auto title_id = std::strtoul(line.c_str(), nullptr, 16); - const auto disabled_list = config->Get("AddOns", "disabled_" + line, ""); - - std::stringstream inner_ss(disabled_list); - std::string inner_line; - std::vector out; - while (std::getline(inner_ss, inner_line, '|')) { - out.push_back(inner_line); - } - - Settings::values.disabled_addons.insert_or_assign(title_id, out); - } - - // Web Service - ReadSetting("WebService", Settings::values.enable_telemetry); - ReadSetting("WebService", Settings::values.web_api_url); - ReadSetting("WebService", Settings::values.sudachi_username); - ReadSetting("WebService", Settings::values.sudachi_token); - - // Network - ReadSetting("Network", Settings::values.network_interface); - - // Android - ReadSetting("Android", AndroidSettings::values.picture_in_picture); - ReadSetting("Android", AndroidSettings::values.screen_layout); -} - -void Config::Initialize(const std::string& config_name) { - const auto fs_config_loc = FS::GetSudachiPath(FS::SudachiPath::ConfigDir); - const auto config_file = fmt::format("{}.ini", config_name); - - switch (type) { - case ConfigType::GlobalConfig: - config_loc = FS::PathToUTF8String(fs_config_loc / config_file); - break; - case ConfigType::PerGameConfig: - config_loc = FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file)); - break; - case ConfigType::InputProfile: - config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file); - LoadINI(DefaultINI::android_config_file); - return; - } - LoadINI(DefaultINI::android_config_file); - ReadValues(); -} diff --git a/src/android/app/src/main/jni/config.h b/src/android/app/src/main/jni/config.h deleted file mode 100644 index 6c13cd0..0000000 --- a/src/android/app/src/main/jni/config.h +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-FileCopyrightText: 2023 sudachi Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include -#include - -#include "common/settings.h" - -class INIReader; - -class Config { - bool LoadINI(const std::string& default_contents = "", bool retry = true); - -public: - enum class ConfigType { - GlobalConfig, - PerGameConfig, - InputProfile, - }; - - explicit Config(const std::string& config_name = "config", - ConfigType config_type = ConfigType::GlobalConfig); - ~Config(); - - void Initialize(const std::string& config_name); - -private: - /** - * Applies a value read from the config to a Setting. - * - * @param group The name of the INI group - * @param setting The sudachi setting to modify - */ - template - void ReadSetting(const std::string& group, Settings::Setting& setting); - - void ReadValues(); - - const ConfigType type; - std::unique_ptr config; - std::string config_loc; - const bool global; -}; diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h deleted file mode 100644 index 23f6436..0000000 --- a/src/android/app/src/main/jni/default_ini.h +++ /dev/null @@ -1,511 +0,0 @@ -// SPDX-FileCopyrightText: 2023 sudachi Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -namespace DefaultINI { - -const char* android_config_file = R"( - -[ControlsP0] -# The input devices and parameters for each Switch native input -# The config section determines the player number where the config will be applied on. For example "ControlsP0", "ControlsP1", ... -# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..." -# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values - -# Indicates if this player should be connected at boot -connected= - -# for button input, the following devices are available: -# - "keyboard" (default) for keyboard input. Required parameters: -# - "code": the code of the key to bind -# - "sdl" for joystick input using SDL. Required parameters: -# - "guid": SDL identification GUID of the joystick -# - "port": the index of the joystick to bind -# - "button"(optional): the index of the button to bind -# - "hat"(optional): the index of the hat to bind as direction buttons -# - "axis"(optional): the index of the axis to bind -# - "direction"(only used for hat): the direction name of the hat to bind. Can be "up", "down", "left" or "right" -# - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is -# triggered if the axis value crosses -# - "direction"(only used for axis): "+" means the button is triggered when the axis value -# is greater than the threshold; "-" means the button is triggered when the axis value -# is smaller than the threshold -button_a= -button_b= -button_x= -button_y= -button_lstick= -button_rstick= -button_l= -button_r= -button_zl= -button_zr= -button_plus= -button_minus= -button_dleft= -button_dup= -button_dright= -button_ddown= -button_lstick_left= -button_lstick_up= -button_lstick_right= -button_lstick_down= -button_sl= -button_sr= -button_home= -button_screenshot= - -# for analog input, the following devices are available: -# - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters: -# - "up", "down", "left", "right": sub-devices for each direction. -# Should be in the format as a button input devices using escape characters, for example, "engine$0keyboard$1code$00" -# - "modifier": sub-devices as a modifier. -# - "modifier_scale": a float number representing the applied modifier scale to the analog input. -# Must be in range of 0.0-1.0. Defaults to 0.5 -# - "sdl" for joystick input using SDL. Required parameters: -# - "guid": SDL identification GUID of the joystick -# - "port": the index of the joystick to bind -# - "axis_x": the index of the axis to bind as x-axis (default to 0) -# - "axis_y": the index of the axis to bind as y-axis (default to 1) -lstick= -rstick= - -# for motion input, the following devices are available: -# - "keyboard" (default) for emulating random motion input from buttons. Required parameters: -# - "code": the code of the key to bind -# - "sdl" for motion input using SDL. Required parameters: -# - "guid": SDL identification GUID of the joystick -# - "port": the index of the joystick to bind -# - "motion": the index of the motion sensor to bind -# - "cemuhookudp" for motion input using Cemu Hook protocol. Required parameters: -# - "guid": the IP address of the cemu hook server encoded to a hex string. for example 192.168.0.1 = "c0a80001" -# - "port": the port of the cemu hook server -# - "pad": the index of the joystick -# - "motion": the index of the motion sensor of the joystick to bind -motionleft= -motionright= - -[ControlsGeneral] -# To use the debug_pad, prepend `debug_pad_` before each button setting above. -# i.e. debug_pad_button_a= - -# Enable debug pad inputs to the guest -# 0 (default): Disabled, 1: Enabled -debug_pad_enabled = - -# Whether to enable or disable vibration -# 0: Disabled, 1 (default): Enabled -vibration_enabled= - -# Whether to enable or disable accurate vibrations -# 0 (default): Disabled, 1: Enabled -enable_accurate_vibrations= - -# Enables controller motion inputs -# 0: Disabled, 1 (default): Enabled -motion_enabled = - -# Defines the udp device's touch screen coordinate system for cemuhookudp devices -# - "min_x", "min_y", "max_x", "max_y" -touch_device= - -# for mapping buttons to touch inputs. -#touch_from_button_map=1 -#touch_from_button_maps_0_name=default -#touch_from_button_maps_0_count=2 -#touch_from_button_maps_0_bind_0=foo -#touch_from_button_maps_0_bind_1=bar -# etc. - -# List of Cemuhook UDP servers, delimited by ','. -# Default: 127.0.0.1:26760 -# Example: 127.0.0.1:26760,123.4.5.67:26761 -udp_input_servers = - -# Enable controlling an axis via a mouse input. -# 0 (default): Off, 1: On -mouse_panning = - -# Set mouse sensitivity. -# Default: 1.0 -mouse_panning_sensitivity = - -# Emulate an analog control stick from keyboard inputs. -# 0 (default): Disabled, 1: Enabled -emulate_analog_keyboard = - -# Enable mouse inputs to the guest -# 0 (default): Disabled, 1: Enabled -mouse_enabled = - -# Enable keyboard inputs to the guest -# 0 (default): Disabled, 1: Enabled -keyboard_enabled = - -[Core] -# Whether to use multi-core for CPU emulation -# 0: Disabled, 1 (default): Enabled -use_multi_core = - -# Enable unsafe extended guest system memory layout (8GB DRAM) -# 0 (default): Disabled, 1: Enabled -use_unsafe_extended_memory_layout = - -[Cpu] -# Adjusts various optimizations. -# Auto-select mode enables choice unsafe optimizations. -# Accurate enables only safe optimizations. -# Unsafe allows any unsafe optimizations. -# 0 (default): Auto-select, 1: Accurate, 2: Enable unsafe optimizations -cpu_accuracy = - -# Allow disabling safe optimizations. -# 0 (default): Disabled, 1: Enabled -cpu_debug_mode = - -# Enable inline page tables optimization (faster guest memory access) -# 0: Disabled, 1 (default): Enabled -cpuopt_page_tables = - -# Enable block linking CPU optimization (reduce block dispatcher use during predictable jumps) -# 0: Disabled, 1 (default): Enabled -cpuopt_block_linking = - -# Enable return stack buffer CPU optimization (reduce block dispatcher use during predictable returns) -# 0: Disabled, 1 (default): Enabled -cpuopt_return_stack_buffer = - -# Enable fast dispatcher CPU optimization (use a two-tiered dispatcher architecture) -# 0: Disabled, 1 (default): Enabled -cpuopt_fast_dispatcher = - -# Enable context elimination CPU Optimization (reduce host memory use for guest context) -# 0: Disabled, 1 (default): Enabled -cpuopt_context_elimination = - -# Enable constant propagation CPU optimization (basic IR optimization) -# 0: Disabled, 1 (default): Enabled -cpuopt_const_prop = - -# Enable miscellaneous CPU optimizations (basic IR optimization) -# 0: Disabled, 1 (default): Enabled -cpuopt_misc_ir = - -# Enable reduction of memory misalignment checks (reduce memory fallbacks for misaligned access) -# 0: Disabled, 1 (default): Enabled -cpuopt_reduce_misalign_checks = - -# Enable Host MMU Emulation (faster guest memory access) -# 0: Disabled, 1 (default): Enabled -cpuopt_fastmem = - -# Enable Host MMU Emulation for exclusive memory instructions (faster guest memory access) -# 0: Disabled, 1 (default): Enabled -cpuopt_fastmem_exclusives = - -# Enable fallback on failure of fastmem of exclusive memory instructions (faster guest memory access) -# 0: Disabled, 1 (default): Enabled -cpuopt_recompile_exclusives = - -# Enable optimization to ignore invalid memory accesses (faster guest memory access) -# 0: Disabled, 1 (default): Enabled -cpuopt_ignore_memory_aborts = - -# Enable unfuse FMA (improve performance on CPUs without FMA) -# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. -# 0: Disabled, 1 (default): Enabled -cpuopt_unsafe_unfuse_fma = - -# Enable faster FRSQRTE and FRECPE -# Only enabled if cpu_accuracy is set to Unsafe. -# 0: Disabled, 1 (default): Enabled -cpuopt_unsafe_reduce_fp_error = - -# Enable faster ASIMD instructions (32 bits only) -# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. -# 0: Disabled, 1 (default): Enabled -cpuopt_unsafe_ignore_standard_fpcr = - -# Enable inaccurate NaN handling -# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. -# 0: Disabled, 1 (default): Enabled -cpuopt_unsafe_inaccurate_nan = - -# Disable address space checks (64 bits only) -# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. -# 0: Disabled, 1 (default): Enabled -cpuopt_unsafe_fastmem_check = - -# Enable faster exclusive instructions -# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. -# 0: Disabled, 1 (default): Enabled -cpuopt_unsafe_ignore_global_monitor = - -[Renderer] -# Which backend API to use. -# 0: OpenGL (unsupported), 1 (default): Vulkan, 2: Null -backend = - -# Whether to enable asynchronous presentation (Vulkan only) -# 0: Off, 1 (default): On -async_presentation = - -# Forces the GPU to run at the maximum possible clocks (thermal constraints will still be applied). -# 0 (default): Disabled, 1: Enabled -force_max_clock = - -# Enable graphics API debugging mode. -# 0 (default): Disabled, 1: Enabled -debug = - -# Enable shader feedback. -# 0 (default): Disabled, 1: Enabled -renderer_shader_feedback = - -# Enable Nsight Aftermath crash dumps -# 0 (default): Disabled, 1: Enabled -nsight_aftermath = - -# Disable shader loop safety checks, executing the shader without loop logic changes -# 0 (default): Disabled, 1: Enabled -disable_shader_loop_safety_checks = - -# Which Vulkan physical device to use (defaults to 0) -vulkan_device = - -# 0: 0.5x (360p/540p) [EXPERIMENTAL] -# 1: 0.75x (540p/810p) [EXPERIMENTAL] -# 2 (default): 1x (720p/1080p) -# 3: 2x (1440p/2160p) -# 4: 3x (2160p/3240p) -# 5: 4x (2880p/4320p) -# 6: 5x (3600p/5400p) -# 7: 6x (4320p/6480p) -resolution_setup = - -# Pixel filter to use when up- or down-sampling rendered frames. -# 0: Nearest Neighbor -# 1 (default): Bilinear -# 2: Bicubic -# 3: Gaussian -# 4: ScaleForce -# 5: AMD FidelityFX™️ Super Resolution [Vulkan Only] -scaling_filter = - -# Anti-Aliasing (AA) -# 0 (default): None, 1: FXAA -anti_aliasing = - -# Whether to use fullscreen or borderless window mode -# 0 (Windows default): Borderless window, 1 (All other default): Exclusive fullscreen -fullscreen_mode = - -# Aspect ratio -# 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Force 16:10, 4: Stretch to Window -aspect_ratio = - -# Anisotropic filtering -# 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x -max_anisotropy = - -# Whether to enable VSync or not. -# OpenGL: Values other than 0 enable VSync -# Vulkan: FIFO is selected if the requested mode is not supported by the driver. -# FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen refresh rate. -# FIFO Relaxed is similar to FIFO but allows tearing as it recovers from a slow down. -# Mailbox can have lower latency than FIFO and does not tear but may drop frames. -# Immediate (no synchronization) just presents whatever is available and can exhibit tearing. -# 0: Immediate (Off), 1 (Default): Mailbox (On), 2: FIFO, 3: FIFO Relaxed -use_vsync = - -# Selects the OpenGL shader backend. NV_gpu_program5 is required for GLASM. If NV_gpu_program5 is -# not available and GLASM is selected, GLSL will be used. -# 0: GLSL, 1 (default): GLASM, 2: SPIR-V -shader_backend = - -# Whether to allow asynchronous shader building. -# 0 (default): Off, 1: On -use_asynchronous_shaders = - -# Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory. -# 0 (default): Off, 1: On -use_reactive_flushing = - -# NVDEC emulation. -# 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding -nvdec_emulation = - -# Accelerate ASTC texture decoding. -# 0 (default): Off, 1: On -accelerate_astc = - -# Turns on the speed limiter, which will limit the emulation speed to the desired speed limit value -# 0: Off, 1: On (default) -use_speed_limit = - -# Limits the speed of the game to run no faster than this value as a percentage of target speed -# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default) -speed_limit = - -# Whether to use disk based shader cache -# 0: Off, 1 (default): On -use_disk_shader_cache = - -# Which gpu accuracy level to use -# 0 (default): Normal, 1: High, 2: Extreme (Very slow) -gpu_accuracy = - -# Whether to use asynchronous GPU emulation -# 0 : Off (slow), 1 (default): On (fast) -use_asynchronous_gpu_emulation = - -# Inform the guest that GPU operations completed more quickly than they did. -# 0: Off, 1 (default): On -use_fast_gpu_time = - -# Force unmodified buffers to be flushed, which can cost performance. -# 0: Off (default), 1: On -use_pessimistic_flushes = - -# Whether to use garbage collection or not for GPU caches. -# 0 (default): Off, 1: On -use_caches_gc = - -# The clear color for the renderer. What shows up on the sides of the bottom screen. -# Must be in range of 0-255. Defaults to 0 for all. -bg_red = -bg_blue = -bg_green = - -[Audio] -# Which audio output engine to use. -# auto (default): Auto-select -# cubeb: Cubeb audio engine (if available) -# sdl2: SDL2 audio engine (if available) -# null: No audio output -output_engine = - -# Which audio device to use. -# auto (default): Auto-select -output_device = - -# Output volume. -# 100 (default): 100%, 0; mute -volume = - -[Data Storage] -# Whether to create a virtual SD card. -# 1: Yes, 0 (default): No -use_virtual_sd = - -# Whether or not to enable gamecard emulation -# 1: Yes, 0 (default): No -gamecard_inserted = - -# Whether or not the gamecard should be emulated as the current game -# If 'gamecard_inserted' is 0 this setting is irrelevant -# 1: Yes, 0 (default): No -gamecard_current_game = - -# Path to an XCI file to use as the gamecard -# If 'gamecard_inserted' is 0 this setting is irrelevant -# If 'gamecard_current_game' is 1 this setting is irrelevant -gamecard_path = - -[System] -# Whether the system is docked -# 1 (default): Yes, 0: No -use_docked_mode = - -# Sets the seed for the RNG generator built into the switch -# rng_seed will be ignored and randomly generated if rng_seed_enabled is false -rng_seed_enabled = -rng_seed = - -# Sets the current time (in seconds since 12:00 AM Jan 1, 1970) that will be used by the time service -# This will auto-increment, with the time set being the time the game is started -# This override will only occur if custom_rtc_enabled is true, otherwise the current time is used -custom_rtc_enabled = -custom_rtc = - -# Sets the systems language index -# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese, -# 7: Korean, 8: Dutch, 9: Portuguese, 10: Russian, 11: Taiwanese, 12: British English, 13: Canadian French, -# 14: Latin American Spanish, 15: Simplified Chinese, 16: Traditional Chinese, 17: Brazilian Portuguese -language_index = - -# The system region that sudachi will use during emulation -# -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan -region_index = - -# The system time zone that sudachi will use during emulation -# 0: Auto-select (default), 1: Default (system archive value), Others: Index for specified time zone -time_zone_index = - -# Sets the sound output mode. -# 0: Mono, 1 (default): Stereo, 2: Surround -sound_index = - -[Miscellaneous] -# A filter which removes logs below a certain logging level. -# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical -log_filter = *:Trace - -# Use developer keys -# 0 (default): Disabled, 1: Enabled -use_dev_keys = - -[Debugging] -# Record frame time data, can be found in the log directory. Boolean value -record_frame_times = -# Determines whether or not sudachi will dump the ExeFS of all games it attempts to load while loading them -dump_exefs=false -# Determines whether or not sudachi will dump all NSOs it attempts to load while loading them -dump_nso=false -# Determines whether or not sudachi will save the filesystem access log. -enable_fs_access_log=false -# Enables verbose reporting services -reporting_services = -# Determines whether or not sudachi will report to the game that the emulated console is in Kiosk Mode -# false: Retail/Normal Mode (default), true: Kiosk Mode -quest_flag = -# Determines whether debug asserts should be enabled, which will throw an exception on asserts. -# false: Disabled (default), true: Enabled -use_debug_asserts = -# Determines whether unimplemented HLE service calls should be automatically stubbed. -# false: Disabled (default), true: Enabled -use_auto_stub = -# Enables/Disables the macro JIT compiler -disable_macro_jit=false -# Determines whether to enable the GDB stub and wait for the debugger to attach before running. -# false: Disabled (default), true: Enabled -use_gdbstub=false -# The port to use for the GDB server, if it is enabled. -gdbstub_port=6543 - -[WebService] -# Whether or not to enable telemetry -# 0: No, 1 (default): Yes -enable_telemetry = -# URL for Web API -web_api_url = https://api.sudachi-emu.org -# Username and token for sudachi Web Service -# See https://profile.sudachi-emu.org/ for more info -sudachi_username = -sudachi_token = - -[Network] -# Name of the network interface device to use with sudachi LAN play. -# e.g. On *nix: 'enp7s0', 'wlp6s0u1u3u3', 'lo' -# e.g. On Windows: 'Ethernet', 'Wi-Fi' -network_interface = - -[AddOns] -# Used to disable add-ons -# List of title IDs of games that will have add-ons disabled (separated by '|'): -title_ids = -# For each title ID, have a key/value pair called `disabled_` equal to the names of the add-ons to disable (sep. by '|') -# e.x. disabled_0100000000010000 = Update|DLC <- disables Updates and DLC on Super Mario Odyssey -)"; -} // namespace DefaultINI diff --git a/src/android/app/src/main/jni/emu_window/emu_window.cpp b/src/android/app/src/main/jni/emu_window/emu_window.cpp deleted file mode 100644 index dae83bf..0000000 --- a/src/android/app/src/main/jni/emu_window/emu_window.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-FileCopyrightText: 2023 sudachi Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include - -#include "common/android/id_cache.h" -#include "common/logging/log.h" -#include "input_common/drivers/android.h" -#include "input_common/drivers/touch_screen.h" -#include "input_common/drivers/virtual_amiibo.h" -#include "input_common/drivers/virtual_gamepad.h" -#include "input_common/main.h" -#include "jni/emu_window/emu_window.h" -#include "jni/native.h" - -void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { - m_window_width = ANativeWindow_getWidth(surface); - m_window_height = ANativeWindow_getHeight(surface); - - // Ensures that we emulate with the correct aspect ratio. - UpdateCurrentFramebufferLayout(m_window_width, m_window_height); - - window_info.render_surface = reinterpret_cast(surface); -} - -void EmuWindow_Android::OnTouchPressed(int id, float x, float y) { - const auto [touch_x, touch_y] = MapToTouchScreen(x, y); - EmulationSession::GetInstance().GetInputSubsystem().GetTouchScreen()->TouchPressed(touch_x, - touch_y, id); -} - -void EmuWindow_Android::OnTouchMoved(int id, float x, float y) { - const auto [touch_x, touch_y] = MapToTouchScreen(x, y); - EmulationSession::GetInstance().GetInputSubsystem().GetTouchScreen()->TouchMoved(touch_x, - touch_y, id); -} - -void EmuWindow_Android::OnTouchReleased(int id) { - EmulationSession::GetInstance().GetInputSubsystem().GetTouchScreen()->TouchReleased(id); -} - -void EmuWindow_Android::OnFrameDisplayed() { - if (!m_first_frame) { - Common::Android::RunJNIOnFiber( - [&](JNIEnv* env) { EmulationSession::GetInstance().OnEmulationStarted(); }); - m_first_frame = true; - } -} - -EmuWindow_Android::EmuWindow_Android(ANativeWindow* surface, - std::shared_ptr driver_library) - : m_driver_library{driver_library} { - LOG_INFO(Frontend, "initializing"); - - if (!surface) { - LOG_CRITICAL(Frontend, "surface is nullptr"); - return; - } - - OnSurfaceChanged(surface); - window_info.type = Core::Frontend::WindowSystemType::Android; -} diff --git a/src/android/app/src/main/jni/emu_window/emu_window.h b/src/android/app/src/main/jni/emu_window/emu_window.h deleted file mode 100644 index 98bf1a0..0000000 --- a/src/android/app/src/main/jni/emu_window/emu_window.h +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-FileCopyrightText: 2023 sudachi Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include -#include - -#include "core/frontend/emu_window.h" -#include "core/frontend/graphics_context.h" -#include "input_common/main.h" - -struct ANativeWindow; - -class GraphicsContext_Android final : public Core::Frontend::GraphicsContext { -public: - explicit GraphicsContext_Android(std::shared_ptr driver_library) - : m_driver_library{driver_library} {} - - ~GraphicsContext_Android() = default; - - std::shared_ptr GetDriverLibrary() override { - return m_driver_library; - } - -private: - std::shared_ptr m_driver_library; -}; - -class EmuWindow_Android final : public Core::Frontend::EmuWindow { - -public: - EmuWindow_Android(ANativeWindow* surface, - std::shared_ptr driver_library); - - ~EmuWindow_Android() = default; - - void OnSurfaceChanged(ANativeWindow* surface); - void OnFrameDisplayed() override; - - void OnTouchPressed(int id, float x, float y); - void OnTouchMoved(int id, float x, float y); - void OnTouchReleased(int id); - - std::unique_ptr CreateSharedContext() const override { - return {std::make_unique(m_driver_library)}; - } - bool IsShown() const override { - return true; - }; - -private: - float m_window_width{}; - float m_window_height{}; - - std::shared_ptr m_driver_library; - - bool m_first_frame = false; -}; diff --git a/src/android/app/src/main/jni/id_cache.cpp b/src/android/app/src/main/jni/id_cache.cpp deleted file mode 100644 index f703fa8..0000000 --- a/src/android/app/src/main/jni/id_cache.cpp +++ /dev/null @@ -1,428 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 sudachi Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include - -#include "common/assert.h" -#include "common/fs/fs_android.h" -#include "jni/applets/software_keyboard.h" -#include "jni/id_cache.h" -#include "video_core/rasterizer_interface.h" - -static JavaVM* s_java_vm; -static jclass s_native_library_class; -static jclass s_disk_cache_progress_class; -static jclass s_load_callback_stage_class; -static jclass s_game_dir_class; -static jmethodID s_game_dir_constructor; -static jmethodID s_exit_emulation_activity; -static jmethodID s_disk_cache_load_progress; -static jmethodID s_on_emulation_started; -static jmethodID s_on_emulation_stopped; -static jmethodID s_on_program_changed; - -static jclass s_game_class; -static jmethodID s_game_constructor; -static jfieldID s_game_title_field; -static jfieldID s_game_path_field; -static jfieldID s_game_program_id_field; -static jfieldID s_game_developer_field; -static jfieldID s_game_version_field; -static jfieldID s_game_is_homebrew_field; - -static jclass s_string_class; -static jclass s_pair_class; -static jmethodID s_pair_constructor; -static jfieldID s_pair_first_field; -static jfieldID s_pair_second_field; - -static jclass s_overlay_control_data_class; -static jmethodID s_overlay_control_data_constructor; -static jfieldID s_overlay_control_data_id_field; -static jfieldID s_overlay_control_data_enabled_field; -static jfieldID s_overlay_control_data_landscape_position_field; -static jfieldID s_overlay_control_data_portrait_position_field; -static jfieldID s_overlay_control_data_foldable_position_field; - -static jclass s_patch_class; -static jmethodID s_patch_constructor; -static jfieldID s_patch_enabled_field; -static jfieldID s_patch_name_field; -static jfieldID s_patch_version_field; -static jfieldID s_patch_type_field; -static jfieldID s_patch_program_id_field; -static jfieldID s_patch_title_id_field; - -static jclass s_double_class; -static jmethodID s_double_constructor; -static jfieldID s_double_value_field; - -static jclass s_integer_class; -static jmethodID s_integer_constructor; -static jfieldID s_integer_value_field; - -static jclass s_boolean_class; -static jmethodID s_boolean_constructor; -static jfieldID s_boolean_value_field; - -static constexpr jint JNI_VERSION = JNI_VERSION_1_6; - -namespace IDCache { - -JNIEnv* GetEnvForThread() { - thread_local static struct OwnedEnv { - OwnedEnv() { - status = s_java_vm->GetEnv(reinterpret_cast(&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; -} - -jclass GetDiskCacheProgressClass() { - return s_disk_cache_progress_class; -} - -jclass GetDiskCacheLoadCallbackStageClass() { - return s_load_callback_stage_class; -} - -jclass GetGameDirClass() { - return s_game_dir_class; -} - -jmethodID GetGameDirConstructor() { - return s_game_dir_constructor; -} - -jmethodID GetExitEmulationActivity() { - return s_exit_emulation_activity; -} - -jmethodID GetDiskCacheLoadProgress() { - return s_disk_cache_load_progress; -} - -jmethodID GetOnEmulationStarted() { - return s_on_emulation_started; -} - -jmethodID GetOnEmulationStopped() { - return s_on_emulation_stopped; -} - -jmethodID GetOnProgramChanged() { - return s_on_program_changed; -} - -jclass GetGameClass() { - return s_game_class; -} - -jmethodID GetGameConstructor() { - return s_game_constructor; -} - -jfieldID GetGameTitleField() { - return s_game_title_field; -} - -jfieldID GetGamePathField() { - return s_game_path_field; -} - -jfieldID GetGameProgramIdField() { - return s_game_program_id_field; -} - -jfieldID GetGameDeveloperField() { - return s_game_developer_field; -} - -jfieldID GetGameVersionField() { - return s_game_version_field; -} - -jfieldID GetGameIsHomebrewField() { - return s_game_is_homebrew_field; -} - -jclass GetStringClass() { - return s_string_class; -} - -jclass GetPairClass() { - return s_pair_class; -} - -jmethodID GetPairConstructor() { - return s_pair_constructor; -} - -jfieldID GetPairFirstField() { - return s_pair_first_field; -} - -jfieldID GetPairSecondField() { - return s_pair_second_field; -} - -jclass GetOverlayControlDataClass() { - return s_overlay_control_data_class; -} - -jmethodID GetOverlayControlDataConstructor() { - return s_overlay_control_data_constructor; -} - -jfieldID GetOverlayControlDataIdField() { - return s_overlay_control_data_id_field; -} - -jfieldID GetOverlayControlDataEnabledField() { - return s_overlay_control_data_enabled_field; -} - -jfieldID GetOverlayControlDataLandscapePositionField() { - return s_overlay_control_data_landscape_position_field; -} - -jfieldID GetOverlayControlDataPortraitPositionField() { - return s_overlay_control_data_portrait_position_field; -} - -jfieldID GetOverlayControlDataFoldablePositionField() { - return s_overlay_control_data_foldable_position_field; -} - -jclass GetPatchClass() { - return s_patch_class; -} - -jmethodID GetPatchConstructor() { - return s_patch_constructor; -} - -jfieldID GetPatchEnabledField() { - return s_patch_enabled_field; -} - -jfieldID GetPatchNameField() { - return s_patch_name_field; -} - -jfieldID GetPatchVersionField() { - return s_patch_version_field; -} - -jfieldID GetPatchTypeField() { - return s_patch_type_field; -} - -jfieldID GetPatchProgramIdField() { - return s_patch_program_id_field; -} - -jfieldID GetPatchTitleIdField() { - return s_patch_title_id_field; -} - -jclass GetDoubleClass() { - return s_double_class; -} - -jmethodID GetDoubleConstructor() { - return s_double_constructor; -} - -jfieldID GetDoubleValueField() { - return s_double_value_field; -} - -jclass GetIntegerClass() { - return s_integer_class; -} - -jmethodID GetIntegerConstructor() { - return s_integer_constructor; -} - -jfieldID GetIntegerValueField() { - return s_integer_value_field; -} - -jclass GetBooleanClass() { - return s_boolean_class; -} - -jmethodID GetBooleanConstructor() { - return s_boolean_constructor; -} - -jfieldID GetBooleanValueField() { - return s_boolean_value_field; -} - -} // namespace IDCache - -#ifdef __cplusplus -extern "C" { -#endif - -jint JNI_OnLoad(JavaVM* vm, void* reserved) { - s_java_vm = vm; - - JNIEnv* env; - if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION) != JNI_OK) - return JNI_ERR; - - // Initialize Java classes - const jclass native_library_class = env->FindClass("org/sudachi/sudachi_emu/NativeLibrary"); - s_native_library_class = reinterpret_cast(env->NewGlobalRef(native_library_class)); - s_disk_cache_progress_class = reinterpret_cast(env->NewGlobalRef( - env->FindClass("org/sudachi/sudachi_emu/disk_shader_cache/DiskShaderCacheProgress"))); - s_load_callback_stage_class = reinterpret_cast(env->NewGlobalRef(env->FindClass( - "org/sudachi/sudachi_emu/disk_shader_cache/DiskShaderCacheProgress$LoadCallbackStage"))); - - const jclass game_dir_class = env->FindClass("org/sudachi/sudachi_emu/model/GameDir"); - s_game_dir_class = reinterpret_cast(env->NewGlobalRef(game_dir_class)); - s_game_dir_constructor = env->GetMethodID(game_dir_class, "", "(Ljava/lang/String;Z)V"); - env->DeleteLocalRef(game_dir_class); - - // Initialize methods - s_exit_emulation_activity = - env->GetStaticMethodID(s_native_library_class, "exitEmulationActivity", "(I)V"); - s_disk_cache_load_progress = - env->GetStaticMethodID(s_disk_cache_progress_class, "loadProgress", "(III)V"); - s_on_emulation_started = - env->GetStaticMethodID(s_native_library_class, "onEmulationStarted", "()V"); - s_on_emulation_stopped = - 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/sudachi/sudachi_emu/model/Game"); - s_game_class = reinterpret_cast(env->NewGlobalRef(game_class)); - s_game_constructor = env->GetMethodID(game_class, "", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/" - "String;Ljava/lang/String;Ljava/lang/String;Z)V"); - s_game_title_field = env->GetFieldID(game_class, "title", "Ljava/lang/String;"); - s_game_path_field = env->GetFieldID(game_class, "path", "Ljava/lang/String;"); - s_game_program_id_field = env->GetFieldID(game_class, "programId", "Ljava/lang/String;"); - s_game_developer_field = env->GetFieldID(game_class, "developer", "Ljava/lang/String;"); - s_game_version_field = env->GetFieldID(game_class, "version", "Ljava/lang/String;"); - s_game_is_homebrew_field = env->GetFieldID(game_class, "isHomebrew", "Z"); - env->DeleteLocalRef(game_class); - - const jclass string_class = env->FindClass("java/lang/String"); - s_string_class = reinterpret_cast(env->NewGlobalRef(string_class)); - env->DeleteLocalRef(string_class); - - const jclass pair_class = env->FindClass("kotlin/Pair"); - s_pair_class = reinterpret_cast(env->NewGlobalRef(pair_class)); - s_pair_constructor = - env->GetMethodID(pair_class, "", "(Ljava/lang/Object;Ljava/lang/Object;)V"); - s_pair_first_field = env->GetFieldID(pair_class, "first", "Ljava/lang/Object;"); - s_pair_second_field = env->GetFieldID(pair_class, "second", "Ljava/lang/Object;"); - env->DeleteLocalRef(pair_class); - - const jclass overlay_control_data_class = - env->FindClass("org/sudachi/sudachi_emu/overlay/model/OverlayControlData"); - s_overlay_control_data_class = - reinterpret_cast(env->NewGlobalRef(overlay_control_data_class)); - s_overlay_control_data_constructor = - env->GetMethodID(overlay_control_data_class, "", - "(Ljava/lang/String;ZLkotlin/Pair;Lkotlin/Pair;Lkotlin/Pair;)V"); - s_overlay_control_data_id_field = - env->GetFieldID(overlay_control_data_class, "id", "Ljava/lang/String;"); - s_overlay_control_data_enabled_field = - env->GetFieldID(overlay_control_data_class, "enabled", "Z"); - s_overlay_control_data_landscape_position_field = - env->GetFieldID(overlay_control_data_class, "landscapePosition", "Lkotlin/Pair;"); - s_overlay_control_data_portrait_position_field = - env->GetFieldID(overlay_control_data_class, "portraitPosition", "Lkotlin/Pair;"); - s_overlay_control_data_foldable_position_field = - env->GetFieldID(overlay_control_data_class, "foldablePosition", "Lkotlin/Pair;"); - env->DeleteLocalRef(overlay_control_data_class); - - const jclass patch_class = env->FindClass("org/sudachi/sudachi_emu/model/Patch"); - s_patch_class = reinterpret_cast(env->NewGlobalRef(patch_class)); - s_patch_constructor = env->GetMethodID( - patch_class, "", - "(ZLjava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V"); - s_patch_enabled_field = env->GetFieldID(patch_class, "enabled", "Z"); - s_patch_name_field = env->GetFieldID(patch_class, "name", "Ljava/lang/String;"); - s_patch_version_field = env->GetFieldID(patch_class, "version", "Ljava/lang/String;"); - s_patch_type_field = env->GetFieldID(patch_class, "type", "I"); - s_patch_program_id_field = env->GetFieldID(patch_class, "programId", "Ljava/lang/String;"); - s_patch_title_id_field = env->GetFieldID(patch_class, "titleId", "Ljava/lang/String;"); - env->DeleteLocalRef(patch_class); - - const jclass double_class = env->FindClass("java/lang/Double"); - s_double_class = reinterpret_cast(env->NewGlobalRef(double_class)); - s_double_constructor = env->GetMethodID(double_class, "", "(D)V"); - s_double_value_field = env->GetFieldID(double_class, "value", "D"); - env->DeleteLocalRef(double_class); - - const jclass int_class = env->FindClass("java/lang/Integer"); - s_integer_class = reinterpret_cast(env->NewGlobalRef(int_class)); - s_integer_constructor = env->GetMethodID(int_class, "", "(I)V"); - s_integer_value_field = env->GetFieldID(int_class, "value", "I"); - env->DeleteLocalRef(int_class); - - const jclass boolean_class = env->FindClass("java/lang/Boolean"); - s_boolean_class = reinterpret_cast(env->NewGlobalRef(boolean_class)); - s_boolean_constructor = env->GetMethodID(boolean_class, "", "(Z)V"); - s_boolean_value_field = env->GetFieldID(boolean_class, "value", "Z"); - env->DeleteLocalRef(boolean_class); - - // Initialize Android Storage - Common::FS::Android::RegisterCallbacks(env, s_native_library_class); - - // Initialize applets - SoftwareKeyboard::InitJNI(env); - - return JNI_VERSION; -} - -void JNI_OnUnload(JavaVM* vm, void* reserved) { - JNIEnv* env; - if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION) != JNI_OK) { - return; - } - - // UnInitialize Android Storage - Common::FS::Android::UnRegisterCallbacks(); - env->DeleteGlobalRef(s_native_library_class); - env->DeleteGlobalRef(s_disk_cache_progress_class); - env->DeleteGlobalRef(s_load_callback_stage_class); - env->DeleteGlobalRef(s_game_dir_class); - env->DeleteGlobalRef(s_game_class); - env->DeleteGlobalRef(s_string_class); - env->DeleteGlobalRef(s_pair_class); - env->DeleteGlobalRef(s_overlay_control_data_class); - env->DeleteGlobalRef(s_patch_class); - env->DeleteGlobalRef(s_double_class); - env->DeleteGlobalRef(s_integer_class); - env->DeleteGlobalRef(s_boolean_class); - - // UnInitialize applets - SoftwareKeyboard::CleanupJNI(env); -} - -#ifdef __cplusplus -} -#endif diff --git a/src/android/app/src/main/jni/id_cache.h b/src/android/app/src/main/jni/id_cache.h deleted file mode 100644 index dc3c41a..0000000 --- a/src/android/app/src/main/jni/id_cache.h +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-FileCopyrightText: 2023 sudachi Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include - -#include "video_core/rasterizer_interface.h" - -namespace IDCache { - -JNIEnv* GetEnvForThread(); -jclass GetNativeLibraryClass(); -jclass GetDiskCacheProgressClass(); -jclass GetDiskCacheLoadCallbackStageClass(); -jclass GetGameDirClass(); -jmethodID GetGameDirConstructor(); -jmethodID GetExitEmulationActivity(); -jmethodID GetDiskCacheLoadProgress(); -jmethodID GetOnEmulationStarted(); -jmethodID GetOnEmulationStopped(); -jmethodID GetOnProgramChanged(); - -jclass GetGameClass(); -jmethodID GetGameConstructor(); -jfieldID GetGameTitleField(); -jfieldID GetGamePathField(); -jfieldID GetGameProgramIdField(); -jfieldID GetGameDeveloperField(); -jfieldID GetGameVersionField(); -jfieldID GetGameIsHomebrewField(); - -jclass GetStringClass(); -jclass GetPairClass(); -jmethodID GetPairConstructor(); -jfieldID GetPairFirstField(); -jfieldID GetPairSecondField(); - -jclass GetOverlayControlDataClass(); -jmethodID GetOverlayControlDataConstructor(); -jfieldID GetOverlayControlDataIdField(); -jfieldID GetOverlayControlDataEnabledField(); -jfieldID GetOverlayControlDataLandscapePositionField(); -jfieldID GetOverlayControlDataPortraitPositionField(); -jfieldID GetOverlayControlDataFoldablePositionField(); - -jclass GetPatchClass(); -jmethodID GetPatchConstructor(); -jfieldID GetPatchEnabledField(); -jfieldID GetPatchNameField(); -jfieldID GetPatchVersionField(); -jfieldID GetPatchTypeField(); -jfieldID GetPatchProgramIdField(); -jfieldID GetPatchTitleIdField(); - -jclass GetDoubleClass(); -jmethodID GetDoubleConstructor(); -jfieldID GetDoubleValueField(); - -jclass GetIntegerClass(); -jmethodID GetIntegerConstructor(); -jfieldID GetIntegerValueField(); - -jclass GetBooleanClass(); -jmethodID GetBooleanConstructor(); -jfieldID GetBooleanValueField(); - -} // namespace IDCache diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp deleted file mode 100644 index 85c05a5..0000000 --- a/src/android/app/src/main/jni/native.cpp +++ /dev/null @@ -1,873 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 sudachi Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include -#include -#include - -#ifdef ARCHITECTURE_arm64 -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common/android/android_common.h" -#include "common/android/id_cache.h" -#include "common/detached_tasks.h" -#include "common/dynamic_library.h" -#include "common/fs/path_util.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 "common/string_util.h" -#include "core/core.h" -#include "core/cpu_manager.h" -#include "core/crypto/key_manager.h" -#include "core/file_sys/card_image.h" -#include "core/file_sys/content_archive.h" -#include "core/file_sys/fs_filesystem.h" -#include "core/file_sys/submission_package.h" -#include "core/file_sys/vfs/vfs.h" -#include "core/file_sys/vfs/vfs_real.h" -#include "core/frontend/applets/cabinet.h" -#include "core/frontend/applets/controller.h" -#include "core/frontend/applets/error.h" -#include "core/frontend/applets/general.h" -#include "core/frontend/applets/mii_edit.h" -#include "core/frontend/applets/profile_select.h" -#include "core/frontend/applets/software_keyboard.h" -#include "core/frontend/applets/web_browser.h" -#include "core/hle/service/am/applet_manager.h" -#include "core/hle/service/am/frontend/applets.h" -#include "core/hle/service/filesystem/filesystem.h" -#include "core/loader/loader.h" -#include "frontend_common/config.h" -#include "hid_core/frontend/emulated_controller.h" -#include "hid_core/hid_core.h" -#include "hid_core/hid_types.h" -#include "jni/native.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 jauto [[maybe_unused]] auto - -static EmulationSession s_instance; - -EmulationSession::EmulationSession() { - m_vfs = std::make_shared(); -} - -EmulationSession& EmulationSession::GetInstance() { - return s_instance; -} - -const Core::System& EmulationSession::System() const { - return m_system; -} - -Core::System& EmulationSession::System() { - return m_system; -} - -FileSys::ManualContentProvider* EmulationSession::GetContentProvider() { - return m_manual_provider.get(); -} - -InputCommon::InputSubsystem& EmulationSession::GetInputSubsystem() { - return m_input_subsystem; -} - -const EmuWindow_Android& EmulationSession::Window() const { - return *m_window; -} - -EmuWindow_Android& EmulationSession::Window() { - return *m_window; -} - -ANativeWindow* EmulationSession::NativeWindow() const { - return m_native_window; -} - -void EmulationSession::SetNativeWindow(ANativeWindow* native_window) { - m_native_window = native_window; -} - -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{}; - - // 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(); - } - - // 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); - } - - // 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); - } - - m_vulkan_library = std::make_shared(handle); -#endif -} - -bool EmulationSession::IsRunning() const { - return m_is_running; -} - -bool EmulationSession::IsPaused() const { - return m_is_running && m_is_paused; -} - -const Core::PerfStatsResults& EmulationSession::PerfStats() { - m_perf_stats = m_system.GetAndResetPerfStats(); - return m_perf_stats; -} - -void EmulationSession::SurfaceChanged() { - if (!IsRunning()) { - return; - } - m_window->OnSurfaceChanged(m_native_window); -} - -void EmulationSession::ConfigureFilesystemProvider(const std::string& filepath) { - const auto file = m_system.GetFilesystem()->OpenFile(filepath, FileSys::OpenMode::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; - } - - 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(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()); - } - } - } -} - -void EmulationSession::InitializeSystem(bool reload) { - if (!reload) { - // Initialize logging system - Common::Log::Initialize(); - Common::Log::SetColorConsoleBackendEnabled(true); - Common::Log::Start(); - - m_input_subsystem.Initialize(); - } - - // Initialize filesystem. - m_system.SetFilesystem(m_vfs); - m_system.GetUserChannel().clear(); - m_manual_provider = std::make_unique(); - m_system.SetContentProvider(std::make_unique()); - m_system.RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual, - m_manual_provider.get()); - m_system.GetFileSystemController().CreateFactories(*m_vfs); -} - -void EmulationSession::SetAppletId(int applet_id) { - m_applet_id = applet_id; - m_system.GetFrontendAppletHolder().SetCurrentAppletId( - static_cast(m_applet_id)); -} - -Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath, - const std::size_t program_index, - const bool frontend_initiated) { - std::scoped_lock lock(m_mutex); - - // Create the render window. - m_window = std::make_unique(m_native_window, m_vulkan_library); - - // Initialize system. - jauto android_keyboard = std::make_unique(); - m_software_keyboard = android_keyboard.get(); - m_system.SetShuttingDown(false); - m_system.ApplySettings(); - Settings::LogSettings(); - m_system.HIDCore().ReloadInputDevices(); - m_system.SetFrontendAppletSet({ - 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. - ConfigureFilesystemProvider(filepath); - - // Load the ROM. - Service::AM::FrontendAppletParameters params{ - .applet_id = static_cast(m_applet_id), - .launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated - : Service::AM::LaunchType::ApplicationInitiated, - .program_index = static_cast(program_index), - }; - m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params); - 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(); }); - - // 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(); - return Core::SystemResultStatus::Success; -} - -void EmulationSession::ShutdownEmulation() { - 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; - - // Unload user input. - m_system.HIDCore().UnloadInputDevices(); - - // Enable all controllers - m_system.HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); - - // 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; - } - - // Tear down the render window. - m_window.reset(); -} - -void EmulationSession::PauseEmulation() { - std::scoped_lock lock(m_mutex); - m_system.Pause(); - m_is_paused = true; -} - -void EmulationSession::UnPauseEmulation() { - std::scoped_lock lock(m_mutex); - m_system.Run(); - m_is_paused = false; -} - -void EmulationSession::HaltEmulation() { - std::scoped_lock lock(m_mutex); - m_is_running = false; - m_cv.notify_one(); -} - -void EmulationSession::RunEmulation() { - { - std::scoped_lock lock(m_mutex); - m_is_running = true; - } - - // 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(m_system.Run()); - - if (m_system.DebuggerEnabled()) { - m_system.InitializeDebugger(); - } - - 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; - } - } - } - - // Reset current applet ID. - m_applet_id = static_cast(Service::AM::AppletId::Application); -} - -Common::Android::SoftwareKeyboard::AndroidKeyboard* EmulationSession::SoftwareKeyboard() { - return m_software_keyboard; -} - -void EmulationSession::LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, - int max) { - JNIEnv* env = Common::Android::GetEnvForThread(); - env->CallStaticVoidMethod(Common::Android::GetDiskCacheProgressClass(), - Common::Android::GetDiskCacheLoadProgress(), static_cast(stage), - static_cast(progress), static_cast(max)); -} - -void EmulationSession::OnEmulationStarted() { - JNIEnv* env = Common::Android::GetEnvForThread(); - env->CallStaticVoidMethod(Common::Android::GetNativeLibraryClass(), - Common::Android::GetOnEmulationStarted()); -} - -void EmulationSession::OnEmulationStopped(Core::SystemResultStatus result) { - JNIEnv* env = Common::Android::GetEnvForThread(); - env->CallStaticVoidMethod(Common::Android::GetNativeLibraryClass(), - Common::Android::GetOnEmulationStopped(), static_cast(result)); -} - -void EmulationSession::ChangeProgram(std::size_t program_index) { - JNIEnv* env = Common::Android::GetEnvForThread(); - env->CallStaticVoidMethod(Common::Android::GetNativeLibraryClass(), - Common::Android::GetOnProgramChanged(), - static_cast(program_index)); -} - -u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) { - auto program_id_string = Common::Android::GetJString(env, jprogramId); - try { - return std::stoull(program_id_string); - } catch (...) { - return 0; - } -} - -static Core::SystemResultStatus RunEmulation(const std::string& filepath, - const size_t program_index, - const bool frontend_initiated) { - MicroProfileOnThreadCreate("EmuThread"); - SCOPE_EXIT { - MicroProfileShutdown(); - }; - - LOG_INFO(Frontend, "starting"); - - if (filepath.empty()) { - LOG_CRITICAL(Frontend, "failed to load: filepath empty!"); - return Core::SystemResultStatus::ErrorLoader; - } - - SCOPE_EXIT { - EmulationSession::GetInstance().ShutdownEmulation(); - }; - - jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index, - frontend_initiated); - if (result != Core::SystemResultStatus::Success) { - return result; - } - - EmulationSession::GetInstance().RunEmulation(); - - return Core::SystemResultStatus::Success; -} - -extern "C" { - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_surfaceChanged(JNIEnv* env, jobject instance, - [[maybe_unused]] jobject surf) { - EmulationSession::GetInstance().SetNativeWindow(ANativeWindow_fromSurface(env, surf)); - EmulationSession::GetInstance().SurfaceChanged(); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_surfaceDestroyed(JNIEnv* env, jobject instance) { - ANativeWindow_release(EmulationSession::GetInstance().NativeWindow()); - EmulationSession::GetInstance().SetNativeWindow(nullptr); - EmulationSession::GetInstance().SurfaceChanged(); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_setAppDirectory(JNIEnv* env, jobject instance, - [[maybe_unused]] jstring j_directory) { - Common::FS::SetAppDirectory(Common::Android::GetJString(env, j_directory)); -} - -int Java_org_sudachi_sudachi_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject instance, - jstring j_file, jobject jcallback) { - auto jlambdaClass = env->GetObjectClass(jcallback); - auto jlambdaInvokeMethod = env->GetMethodID( - jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); - const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) { - auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod, - Common::Android::ToJDouble(env, max), - Common::Android::ToJDouble(env, progress)); - return Common::Android::GetJBoolean(env, jwasCancelled); - }; - - return static_cast( - ContentManager::InstallNSP(EmulationSession::GetInstance().System(), - *EmulationSession::GetInstance().System().GetFilesystem(), - Common::Android::GetJString(env, j_file), callback)); -} - -jboolean Java_org_sudachi_sudachi_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* env, jobject jobj, - jstring jprogramId, - jstring jupdatePath) { - u64 program_id = EmulationSession::GetProgramId(env, jprogramId); - std::string updatePath = Common::Android::GetJString(env, jupdatePath); - std::shared_ptr nsp = std::make_shared( - EmulationSession::GetInstance().System().GetFilesystem()->OpenFile( - updatePath, FileSys::OpenMode::Read)); - for (const auto& item : nsp->GetNCAs()) { - for (const auto& nca_details : item.second) { - if (nca_details.second->GetName().ends_with(".cnmt.nca")) { - auto update_id = nca_details.second->GetTitleId() & ~0xFFFULL; - if (update_id == program_id) { - return true; - } - } - } - } - return false; -} - -void JNICALL Java_org_sudachi_sudachi_1emu_NativeLibrary_initializeGpuDriver(JNIEnv* env, jclass clazz, - jstring hook_lib_dir, - jstring custom_driver_dir, - jstring custom_driver_name, - jstring file_redirect_dir) { - EmulationSession::GetInstance().InitializeGpuDriver( - Common::Android::GetJString(env, hook_lib_dir), - Common::Android::GetJString(env, custom_driver_dir), - Common::Android::GetJString(env, custom_driver_name), - Common::Android::GetJString(env, file_redirect_dir)); -} - -[[maybe_unused]] static bool CheckKgslPresent() { - constexpr auto KgslPath{"/dev/kgsl-3d0"}; - - return access(KgslPath, F_OK) == 0; -} - -[[maybe_unused]] bool SupportsCustomDriver() { - return android_get_device_api_level() >= 28 && CheckKgslPresent(); -} - -jboolean JNICALL Java_org_sudachi_sudachi_1emu_utils_GpuDriverHelper_supportsCustomDriverLoading( - JNIEnv* env, jobject instance) { -#ifdef ARCHITECTURE_arm64 - // If the KGSL device exists custom drivers can be loaded using adrenotools - return SupportsCustomDriver(); -#else - return false; -#endif -} - -jobjectArray Java_org_sudachi_sudachi_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 = Common::Android::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(handle); - InputCommon::InputSubsystem input_subsystem; - auto window = - std::make_unique(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, 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, Common::Android::GetStringClass(), Common::Android::ToJString(env, version_string)); - env->SetObjectArrayElement(j_driver_info, 1, - Common::Android::ToJString(env, device.GetDriverName())); - return j_driver_info; -} - -jboolean Java_org_sudachi_sudachi_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) { - Core::Crypto::KeyManager::Instance().ReloadKeys(); - return static_cast(Core::Crypto::KeyManager::Instance().AreKeysLoaded()); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_unpauseEmulation(JNIEnv* env, jclass clazz) { - EmulationSession::GetInstance().UnPauseEmulation(); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_pauseEmulation(JNIEnv* env, jclass clazz) { - EmulationSession::GetInstance().PauseEmulation(); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_stopEmulation(JNIEnv* env, jclass clazz) { - EmulationSession::GetInstance().HaltEmulation(); -} - -jboolean Java_org_sudachi_sudachi_1emu_NativeLibrary_isRunning(JNIEnv* env, jclass clazz) { - return static_cast(EmulationSession::GetInstance().IsRunning()); -} - -jboolean Java_org_sudachi_sudachi_1emu_NativeLibrary_isPaused(JNIEnv* env, jclass clazz) { - return static_cast(EmulationSession::GetInstance().IsPaused()); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass clazz, - jboolean reload) { - // Initialize the emulated system. - if (!reload) { - EmulationSession::GetInstance().System().Initialize(); - } - EmulationSession::GetInstance().InitializeSystem(reload); -} - -jdoubleArray Java_org_sudachi_sudachi_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jclass clazz) { - jdoubleArray j_stats = env->NewDoubleArray(4); - - if (EmulationSession::GetInstance().IsRunning()) { - jconst results = EmulationSession::GetInstance().PerfStats(); - - // 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; -} - -jstring Java_org_sudachi_sudachi_1emu_NativeLibrary_getCpuBackend(JNIEnv* env, jclass clazz) { - if (Settings::IsNceEnabled()) { - return Common::Android::ToJString(env, "NCE"); - } - - return Common::Android::ToJString(env, "JIT"); -} - -jstring Java_org_sudachi_sudachi_1emu_NativeLibrary_getGpuDriver(JNIEnv* env, jobject jobj) { - return Common::Android::ToJString( - env, EmulationSession::GetInstance().System().GPU().Renderer().GetDeviceVendor()); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_applySettings(JNIEnv* env, jobject jobj) { - EmulationSession::GetInstance().System().ApplySettings(); - EmulationSession::GetInstance().System().HIDCore().ReloadInputDevices(); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj) { - Settings::LogSettings(); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path, - jint j_program_index, - jboolean j_frontend_initiated) { - const std::string path = Common::Android::GetJString(env, j_path); - - const Core::SystemResultStatus result{ - RunEmulation(path, j_program_index, j_frontend_initiated)}; - if (result != Core::SystemResultStatus::Success) { - env->CallStaticVoidMethod(Common::Android::GetNativeLibraryClass(), - Common::Android::GetExitEmulationActivity(), - static_cast(result)); - } -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_logDeviceInfo(JNIEnv* env, jclass clazz) { - LOG_INFO(Frontend, "sudachi Version: {}-{}", Common::g_scm_branch, Common::g_scm_desc); - LOG_INFO(Frontend, "Host OS: Android API level {}", android_get_device_api_level()); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_submitInlineKeyboardText(JNIEnv* env, jclass clazz, - jstring j_text) { - const std::u16string input = Common::UTF8ToUTF16(Common::Android::GetJString(env, j_text)); - EmulationSession::GetInstance().SoftwareKeyboard()->SubmitInlineKeyboardText(input); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_submitInlineKeyboardInput(JNIEnv* env, jclass clazz, - jint j_key_code) { - EmulationSession::GetInstance().SoftwareKeyboard()->SubmitInlineKeyboardInput(j_key_code); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv* env, - jobject instance) { - const auto nand_dir = Common::FS::GetSudachiPath(Common::FS::SudachiPath::NANDDir); - auto vfs_nand_dir = EmulationSession::GetInstance().System().GetFilesystem()->OpenDirectory( - Common::FS::PathToUTF8String(nand_dir), FileSys::OpenMode::Read); - - const auto user_id = EmulationSession::GetInstance().System().GetProfileManager().GetUser( - static_cast(0)); - ASSERT(user_id); - - const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( - {}, vfs_nand_dir, FileSys::SaveDataSpaceId::User, FileSys::SaveDataType::Account, 1, - user_id->AsU128(), 0); - - const auto full_path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path); - if (!Common::FS::CreateParentDirs(full_path)) { - LOG_WARNING(Frontend, "Failed to create full path of the default user's save directory"); - } -} - -jstring Java_org_sudachi_sudachi_1emu_NativeLibrary_getAppletLaunchPath(JNIEnv* env, jclass clazz, - jlong jid) { - auto bis_system = - EmulationSession::GetInstance().System().GetFileSystemController().GetSystemNANDContents(); - if (!bis_system) { - return Common::Android::ToJString(env, ""); - } - - auto applet_nca = - bis_system->GetEntry(static_cast(jid), FileSys::ContentRecordType::Program); - if (!applet_nca) { - return Common::Android::ToJString(env, ""); - } - - return Common::Android::ToJString(env, applet_nca->GetFullPath()); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz, - jint jappletId) { - EmulationSession::GetInstance().SetAppletId(jappletId); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz, - jint jcabinetMode) { - EmulationSession::GetInstance().System().GetFrontendAppletHolder().SetCabinetMode( - static_cast(jcabinetMode)); -} - -jboolean Java_org_sudachi_sudachi_1emu_NativeLibrary_isFirmwareAvailable(JNIEnv* env, jclass clazz) { - auto bis_system = - EmulationSession::GetInstance().System().GetFileSystemController().GetSystemNANDContents(); - if (!bis_system) { - return false; - } - - // Query an applet to see if it's available - auto applet_nca = - bis_system->GetEntry(0x010000000000100Dull, FileSys::ContentRecordType::Program); - if (!applet_nca) { - return false; - } - return true; -} - -jobjectArray Java_org_sudachi_sudachi_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env, jobject jobj, - jstring jpath, - jstring jprogramId) { - const auto path = Common::Android::GetJString(env, jpath); - const auto vFile = - Core::GetGameFileFromPath(EmulationSession::GetInstance().System().GetFilesystem(), path); - if (vFile == nullptr) { - return nullptr; - } - - auto& system = EmulationSession::GetInstance().System(); - auto program_id = EmulationSession::GetProgramId(env, jprogramId); - const FileSys::PatchManager pm{program_id, system.GetFileSystemController(), - system.GetContentProvider()}; - const auto loader = Loader::GetLoader(system, vFile); - - FileSys::VirtualFile update_raw; - loader->ReadUpdateRaw(update_raw); - - auto patches = pm.GetPatches(update_raw); - jobjectArray jpatchArray = - env->NewObjectArray(patches.size(), Common::Android::GetPatchClass(), nullptr); - int i = 0; - for (const auto& patch : patches) { - jobject jpatch = env->NewObject( - Common::Android::GetPatchClass(), Common::Android::GetPatchConstructor(), patch.enabled, - Common::Android::ToJString(env, patch.name), - Common::Android::ToJString(env, patch.version), static_cast(patch.type), - Common::Android::ToJString(env, std::to_string(patch.program_id)), - Common::Android::ToJString(env, std::to_string(patch.title_id))); - env->SetObjectArrayElement(jpatchArray, i, jpatch); - ++i; - } - return jpatchArray; -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_removeUpdate(JNIEnv* env, jobject jobj, - jstring jprogramId) { - auto program_id = EmulationSession::GetProgramId(env, jprogramId); - ContentManager::RemoveUpdate(EmulationSession::GetInstance().System().GetFileSystemController(), - program_id); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_removeDLC(JNIEnv* env, jobject jobj, - jstring jprogramId) { - auto program_id = EmulationSession::GetProgramId(env, jprogramId); - ContentManager::RemoveAllDLC(EmulationSession::GetInstance().System(), program_id); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_removeMod(JNIEnv* env, jobject jobj, jstring jprogramId, - jstring jname) { - auto program_id = EmulationSession::GetProgramId(env, jprogramId); - ContentManager::RemoveMod(EmulationSession::GetInstance().System().GetFileSystemController(), - program_id, Common::Android::GetJString(env, jname)); -} - -jobjectArray Java_org_sudachi_sudachi_1emu_NativeLibrary_verifyInstalledContents(JNIEnv* env, - jobject jobj, - jobject jcallback) { - auto jlambdaClass = env->GetObjectClass(jcallback); - auto jlambdaInvokeMethod = env->GetMethodID( - jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); - const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) { - auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod, - Common::Android::ToJDouble(env, max), - Common::Android::ToJDouble(env, progress)); - return Common::Android::GetJBoolean(env, jwasCancelled); - }; - - auto& session = EmulationSession::GetInstance(); - std::vector result = ContentManager::VerifyInstalledContents( - session.System(), *session.GetContentProvider(), callback); - jobjectArray jresult = env->NewObjectArray(result.size(), Common::Android::GetStringClass(), - Common::Android::ToJString(env, "")); - for (size_t i = 0; i < result.size(); ++i) { - env->SetObjectArrayElement(jresult, i, Common::Android::ToJString(env, result[i])); - } - return jresult; -} - -jint Java_org_sudachi_sudachi_1emu_NativeLibrary_verifyGameContents(JNIEnv* env, jobject jobj, - jstring jpath, jobject jcallback) { - auto jlambdaClass = env->GetObjectClass(jcallback); - auto jlambdaInvokeMethod = env->GetMethodID( - jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); - const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) { - auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod, - Common::Android::ToJDouble(env, max), - Common::Android::ToJDouble(env, progress)); - return Common::Android::GetJBoolean(env, jwasCancelled); - }; - auto& session = EmulationSession::GetInstance(); - return static_cast(ContentManager::VerifyGameContents( - session.System(), Common::Android::GetJString(env, jpath), callback)); -} - -jstring Java_org_sudachi_sudachi_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject jobj, - jstring jprogramId) { - auto program_id = EmulationSession::GetProgramId(env, jprogramId); - if (program_id == 0) { - return Common::Android::ToJString(env, ""); - } - - auto& system = EmulationSession::GetInstance().System(); - - Service::Account::ProfileManager manager; - // TODO: Pass in a selected user once we get the relevant UI working - const auto user_id = manager.GetUser(static_cast(0)); - ASSERT(user_id); - - const auto nandDir = Common::FS::GetSudachiPath(Common::FS::SudachiPath::NANDDir); - auto vfsNandDir = system.GetFilesystem()->OpenDirectory(Common::FS::PathToUTF8String(nandDir), - FileSys::OpenMode::Read); - - const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( - {}, vfsNandDir, FileSys::SaveDataSpaceId::User, FileSys::SaveDataType::Account, program_id, - user_id->AsU128(), 0); - return Common::Android::ToJString(env, user_save_data_path); -} - -jstring Java_org_sudachi_sudachi_1emu_NativeLibrary_getDefaultProfileSaveDataRoot(JNIEnv* env, - jobject jobj, - jboolean jfuture) { - Service::Account::ProfileManager manager; - // TODO: Pass in a selected user once we get the relevant UI working - const auto user_id = manager.GetUser(static_cast(0)); - ASSERT(user_id); - - const auto user_save_data_root = - FileSys::SaveDataFactory::GetUserGameSaveDataRoot(user_id->AsU128(), jfuture); - return Common::Android::ToJString(env, user_save_data_root); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_addFileToFilesystemProvider(JNIEnv* env, jobject jobj, - jstring jpath) { - EmulationSession::GetInstance().ConfigureFilesystemProvider( - Common::Android::GetJString(env, jpath)); -} - -void Java_org_sudachi_sudachi_1emu_NativeLibrary_clearFilesystemProvider(JNIEnv* env, jobject jobj) { - EmulationSession::GetInstance().GetContentProvider()->ClearAllEntries(); -} - -jboolean Java_org_sudachi_sudachi_1emu_NativeLibrary_areKeysPresent(JNIEnv* env, jobject jobj) { - auto& system = EmulationSession::GetInstance().System(); - system.GetFileSystemController().CreateFactories(*system.GetFilesystem()); - return ContentManager::AreKeysPresent(); -} - -} // extern "C" diff --git a/src/android/app/src/main/jniLibs/arm64-v8a/libVkLayer_khronos_validation.so b/src/android/app/src/main/jniLibs/arm64-v8a/libVkLayer_khronos_validation.so new file mode 100644 index 0000000..9bbff1c Binary files /dev/null and b/src/android/app/src/main/jniLibs/arm64-v8a/libVkLayer_khronos_validation.so differ