From dbb485b09ae2af1016f8ec4d3398e146a6db2272 Mon Sep 17 00:00:00 2001 From: swurl Date: Fri, 11 Apr 2025 14:46:05 -0400 Subject: [PATCH 1/5] switch submodules to our forks Signed-off-by: swurl --- .gitmodules | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/.gitmodules b/.gitmodules index 3a800336a3..ce5adfe266 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,73 +3,73 @@ [submodule "enet"] path = externals/enet - url = https://github.com/lsalzman/enet.git + url = https://git.eden-emu.dev/eden-emu/enet.git [submodule "cubeb"] path = externals/cubeb - url = https://github.com/mozilla/cubeb.git + url = https://git.eden-emu.dev/eden-emu/cubeb.git [submodule "dynarmic"] path = externals/dynarmic - url = https://github.com/eden-emulator/dynarmic.git + url = https://git.eden-emu.dev/eden-emu/dynarmic.git [submodule "libusb"] path = externals/libusb/libusb - url = https://github.com/libusb/libusb.git + url = https://git.eden-emu.dev/eden-emu/libusb.git [submodule "discord-rpc"] path = externals/discord-rpc - url = https://github.com/eden-emulator/discord-rpc.git + url = https://git.eden-emu.dev/eden-emu/discord-rpc.git [submodule "Vulkan-Headers"] path = externals/Vulkan-Headers - url = https://github.com/KhronosGroup/Vulkan-Headers.git + url = https://git.eden-emu.dev/eden-emu/Vulkan-Headers.git [submodule "sirit"] path = externals/sirit - url = https://github.com/eden-emulator/sirit.git + url = https://git.eden-emu.dev/eden-emu/sirit.git [submodule "mbedtls"] path = externals/mbedtls - url = https://github.com/eden-emulator/mbedtls.git + url = https://git.eden-emu.dev/eden-emu/mbedtls.git [submodule "xbyak"] path = externals/xbyak - url = https://github.com/herumi/xbyak.git + url = https://git.eden-emu.dev/eden-emu/xbyak.git [submodule "opus"] path = externals/opus - url = https://github.com/xiph/opus.git + url = https://git.eden-emu.dev/eden-emu/opus.git [submodule "SDL"] path = externals/SDL - url = https://github.com/libsdl-org/SDL.git + url = https://git.eden-emu.dev/eden-emu/SDL.git [submodule "cpp-httplib"] path = externals/cpp-httplib - url = https://github.com/yhirose/cpp-httplib.git + url = https://git.eden-emu.dev/eden-emu/cpp-httplib.git [submodule "ffmpeg"] path = externals/ffmpeg/ffmpeg - url = https://github.com/FFmpeg/FFmpeg.git + url = https://git.eden-emu.dev/eden-emu/FFmpeg.git [submodule "vcpkg"] path = externals/vcpkg - url = https://github.com/microsoft/vcpkg.git + url = https://git.eden-emu.dev/eden-emu/vcpkg.git [submodule "cpp-jwt"] path = externals/cpp-jwt - url = https://github.com/arun11299/cpp-jwt.git + url = https://git.eden-emu.dev/eden-emu/cpp-jwt.git [submodule "libadrenotools"] path = externals/libadrenotools - url = https://github.com/bylaws/libadrenotools.git + url = https://git.eden-emu.dev/eden-emu/libadrenotools.git [submodule "tzdb_to_nx"] path = externals/nx_tzdb/tzdb_to_nx - url = https://github.com/lat9nq/tzdb_to_nx.git + url = https://git.eden-emu.dev/eden-emu/tzdb_to_nx.git [submodule "VulkanMemoryAllocator"] path = externals/VulkanMemoryAllocator - url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git + url = https://git.eden-emu.dev/eden-emu/VulkanMemoryAllocator.git [submodule "breakpad"] path = externals/breakpad - url = https://github.com/eden-emulator/breakpad.git + url = https://git.eden-emu.dev/eden-emu/breakpad.git [submodule "simpleini"] path = externals/simpleini - url = https://github.com/brofield/simpleini.git + url = https://git.eden-emu.dev/eden-emu/simpleini.git [submodule "oaknut"] path = externals/oaknut - url = https://github.com/merryhime/oaknut + url = https://git.eden-emu.dev/eden-emu/oaknut.git [submodule "Vulkan-Utility-Libraries"] path = externals/Vulkan-Utility-Libraries - url = https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git + url = https://git.eden-emu.dev/eden-emu/Vulkan-Utility-Libraries.git [submodule "oboe"] path = externals/oboe - url = https://github.com/eden-emulator/oboe.git + url = https://git.eden-emu.dev/eden-emu/oboe.git [submodule "externals/boost-headers"] path = externals/boost-headers - url = https://github.com/boostorg/headers.git + url = https://git.eden-emu.dev/eden-emu/headers.git From e0795f2b4012a643517ee62c0ff83f824317df05 Mon Sep 17 00:00:00 2001 From: JPikachu Date: Fri, 11 Apr 2025 02:26:37 +0100 Subject: [PATCH 2/5] Service: Add AliasRegionExtraSize Thanks to Briar for finding and testing the Service Credit: Antique - [Sudachi] Dev (https://sudachi.emuplace.app/) --- src/core/hle/kernel/svc/svc_info.cpp | 7 ++++++- src/core/hle/kernel/svc_types.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp index 231e4d0e1b..1814f5e90e 100644 --- a/src/core/hle/kernel/svc/svc_info.cpp +++ b/src/core/hle/kernel/svc/svc_info.cpp @@ -37,7 +37,8 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle case InfoType::TotalNonSystemMemorySize: case InfoType::UsedNonSystemMemorySize: case InfoType::IsApplication: - case InfoType::FreeThreadCount: { + case InfoType::FreeThreadCount: + case InfoType::AliasRegionExtraSize: { R_UNLESS(info_sub_id == 0, ResultInvalidEnumValue); const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); @@ -134,6 +135,10 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle } R_SUCCEED(); + case InfoType::AliasRegionExtraSize: + // TODO (jarrodnorwell): do this when KIP's NPDM header is finished + R_SUCCEED(); + default: break; } diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h index ab432ea78b..d02548ba73 100644 --- a/src/core/hle/kernel/svc_types.h +++ b/src/core/hle/kernel/svc_types.h @@ -153,6 +153,7 @@ enum class InfoType : u32 { ThreadTickCount = 25, IsSvcPermitted = 26, IoRegionHint = 27, + AliasRegionExtraSize = 28, MesosphereMeta = 65000, MesosphereCurrentProcess = 65001, From d29d7b931c6ae8c035992d7a15d96a0c087095db Mon Sep 17 00:00:00 2001 From: JPikachu Date: Sat, 12 Apr 2025 16:18:43 +0000 Subject: [PATCH 3/5] Update README.md --- README.md | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index d258584bfa..25fad0ee7e 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,26 @@


- yuzu + Eden
- yuzu + Eden

-

yuzu is the world's most popular, open-source, Nintendo Switch emulator — started by the creators of Citra. +

Eden is the world's most popular, open-source, Nintendo Switch emulator forked from Yuzu emulator — started by the former Citron developer Camille LeVay and the Eden team.
It is written in C++ with portability in mind, and we actively maintain builds for Windows, Linux and Android.

- - Azure Mainline CI Build Status - - Discord + Discord is not yet public.

@@ -38,37 +35,38 @@ It is written in C++ with portability in mind, and we actively maintain builds f ## Compatibility -The emulator is capable of running most commercial games at full speed, provided you meet the [necessary hardware requirements](https://yuzu-emu.org/help/quickstart/#hardware-requirements). +The emulator is capable of running most commercial games at full speed, provided you meet the necessary hardware requirements. -For a full list of games yuzu supports, please visit our [Compatibility page](https://yuzu-emu.org/game/). +For a list of games yuzu supports, please be patient as this will come eventually. -Check out our [website](https://yuzu-emu.org/) for the latest news on exciting features, monthly progress reports, and more! +Check out our [website](W.I.P) for the latest news on exciting features, monthly progress reports, and more! ## Development -Most of the development happens on GitHub. It's also where [our central repository](https://github.com/yuzu-emu/yuzu) is hosted. For development discussion, please join us on [Discord](https://discord.com/invite/u77vRWY). +Most of the development happens on our git. It's also where [our central repository](https://git.eden-emu.dev/eden-emu/eden) is hosted. For development discussion, please wait join us on [Discord](W.I.P) once it's public. -If you want to contribute, please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). +If you want to contribute we are open to new devs and prs, please make sure your work is of a high standard and you have properly documented it. You can also contact any of the developers on Discord in order to know about the current state of the emulator. If you want to contribute to the user interface translation project, please check out the [yuzu project on transifex](https://www.transifex.com/yuzu-emulator/yuzu). We centralize translation work there, and periodically upstream translations. ## Building -* __Windows__: [Windows Build](https://github.com/yuzu-emu/yuzu/wiki/Building-For-Windows) -* __Linux__: [Linux Build](https://github.com/yuzu-emu/yuzu/wiki/Building-For-Linux) +* __Windows__: [Windows Building Guide](W.I.P) +* __Linux__: [Linux Building Guide](W.I.P) +* __Android__: [Android Building Guide](W.I.P) ## Download -You can download the latest releases automatically via the installer on our [downloads](https://yuzu-emu.org/downloads/) page. +You can download the latest releases from [here](https://git.eden-emu.dev/eden-emu/eden/releases) once public. ## Support -If you enjoy the project and want to support us financially, check out our Patreon! - - - +If you enjoy the project and want to support us financially, check out Camille's donations page! +
+
+ Donations are not available yet.
Any donations received will go towards things like: @@ -78,8 +76,8 @@ Any donations received will go towards things like: * Software licenses (e.g. Visual Studio, IDA Pro, etc.) * Additional hardware (e.g. GPUs as-needed to improve rendering support, other peripherals to add support for, etc.) -If you wish to support us a different way, please join our [Discord](https://discord.gg/u77vRWY) and talk to bunnei. You may also contact: donations@yuzu-emu.org. +If you wish to support us a different way, please join our [Discord](W.I.P), once public, and talk to Camille. ## License -yuzu is licensed under the GPLv3 (or any later version). Refer to the [LICENSE.txt](https://github.com/yuzu-emu/yuzu/blob/master/LICENSE.txt) file. +Eden is licensed under the GPLv3 (or any later version). Refer to the [LICENSE.txt](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/LICENSE.txt) file. From 50ac5e935a6656df061b224e3d4e9b1bfc6cdca2 Mon Sep 17 00:00:00 2001 From: JPikachu Date: Sat, 12 Apr 2025 17:05:56 +0000 Subject: [PATCH 4/5] Update README.md (again) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 25fad0ee7e..826b885146 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@
-

Eden is the world's most popular, open-source, Nintendo Switch emulator forked from Yuzu emulator — started by the former Citron developer Camille LeVay and the Eden team. +

Eden is the world's most popular, open-source, Nintendo Switch emulator forked from Yuzu emulator — started by the former Citron developer Camille LeVey and the Eden team.
It is written in C++ with portability in mind, and we actively maintain builds for Windows, Linux and Android.

From fe51be43c195a716d1d7eab5da9ae99017566d8d Mon Sep 17 00:00:00 2001 From: Briar <205427297+icy-briar@users.noreply.github.com> Date: Sun, 13 Apr 2025 05:36:30 +0200 Subject: [PATCH 5/5] android: Enhance FPS Overlay with more customizable options - Now the fps follows theme color set in settings - Added the ability to toggle stats on and off depending on user preference - Now you are able to change the fps position and add a background behind it for easier reding New added stats for the overlay are FPS FRAMETIME, SPEED, APP_RAM_USAGE, SYSTEM_RAM_USAGE, BATTERY_TEMPERATURE, --- .../features/settings/model/BooleanSetting.kt | 10 +- .../features/settings/model/IntSetting.kt | 1 + .../features/settings/model/Settings.kt | 2 + .../settings/model/view/SettingsItem.kt | 65 ++++ .../settings/ui/SettingsFragmentPresenter.kt | 27 ++ .../yuzu_emu/fragments/EmulationFragment.kt | 308 +++++++++++------- .../app/src/main/jni/android_settings.h | 20 +- .../app/src/main/res/drawable/ic_frames.xml | 32 ++ .../main/res/layout/fragment_emulation.xml | 6 +- .../src/main/res/layout/header_in_game.xml | 66 +++- .../main/res/menu/menu_overlay_options.xml | 9 +- .../src/main/res/values-night/yuzu_colors.xml | 1 + .../app/src/main/res/values/arrays.xml | 17 + .../app/src/main/res/values/strings.xml | 31 ++ .../app/src/main/res/values/yuzu_colors.xml | 1 + 15 files changed, 455 insertions(+), 141 deletions(-) create mode 100644 src/android/app/src/main/res/drawable/ic_frames.xml diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index 6644784729..e3d76d4931 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt @@ -26,7 +26,15 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { SHOW_PERFORMANCE_OVERLAY("show_performance_overlay"), SHOW_INPUT_OVERLAY("show_input_overlay"), TOUCHSCREEN("touchscreen"), - SHOW_THERMAL_OVERLAY("show_thermal_overlay"); + SHOW_THERMAL_OVERLAY("show_thermal_overlay"), + SHOW_FPS("show_fps"), + SHOW_FRAMETIME("show_frame_time"), + SHOW_SPEED("show_speed"), + SHOW_APP_RAM_USAGE("show_app_ram_usage"), + SHOW_SYSTEM_RAM_USAGE("show_system_ram_usage"), + SHOW_BAT_TEMPERATURE("show_bat_temperature"), + OVERLAY_BACKGROUND("overlay_background"),; + override fun getBoolean(needsGlobal: Boolean): Boolean = NativeConfig.getBoolean(key, needsGlobal) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt index 0165cb2d1d..b9658d0f67 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt @@ -26,6 +26,7 @@ enum class IntSetting(override val key: String) : AbstractIntSetting { OVERLAY_OPACITY("control_opacity"), LOCK_DRAWER("lock_drawer"), VERTICAL_ALIGNMENT("vertical_alignment"), + PERF_OVERLAY_POSITION("perf_overlay_position"), FSR_SHARPENING_SLIDER("fsr_sharpening_slider"); override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt index e189c21560..a4d745621a 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt @@ -12,6 +12,7 @@ object Settings { SECTION_ROOT(R.string.advanced_settings), SECTION_SYSTEM(R.string.preferences_system), SECTION_RENDERER(R.string.preferences_graphics), + SECTION_PERFORMANCE_STATS(R.string.show_stats_overlay), SECTION_AUDIO(R.string.preferences_audio), SECTION_INPUT(R.string.preferences_controls), SECTION_INPUT_PLAYER_ONE, @@ -32,6 +33,7 @@ object Settings { const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch" const val PREF_SHOULD_SHOW_PRE_ALPHA_WARNING = "ShouldShowPreAlphaWarning" const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown" + const val SECTION_STATS_OVERLAY = "Stats Overlay" // Deprecated input overlay preference keys const val PREF_CONTROL_SCALE = "controlScale" diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index 5fdf983185..8b54ec23e7 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -220,6 +220,71 @@ abstract class SettingsItem( valuesId = R.array.rendererResolutionValues ) ) + put( + SwitchSetting( + BooleanSetting.SHOW_PERFORMANCE_OVERLAY, + R.string.enable_stats_overlay_, + descriptionId = R.string.stats_overlay_options_description + ) + ) + put( + SwitchSetting( + BooleanSetting.OVERLAY_BACKGROUND, + R.string.overlay_background, + descriptionId = R.string.overlay_background_description + ) + ) + put( + SingleChoiceSetting( + IntSetting.PERF_OVERLAY_POSITION, + titleId = R.string.overlay_position, + descriptionId = R.string.overlay_position_description, + choicesId = R.array.statsPosition, + valuesId = R.array.staticThemeValues + ) + ) + put( + SwitchSetting( + BooleanSetting.SHOW_FPS, + R.string.show_fps, + descriptionId = R.string.show_fps_description + ) + ) + put( + SwitchSetting( + BooleanSetting.SHOW_FRAMETIME, + R.string.show_frametime, + descriptionId = R.string.show_frametime_description + ) + ) + put( + SwitchSetting( + BooleanSetting.SHOW_SPEED, + R.string.show_speed, + descriptionId = R.string.show_speed_description + ) + ) + put( + SwitchSetting( + BooleanSetting.SHOW_APP_RAM_USAGE, + R.string.show_app_ram_usage, + descriptionId = R.string.show_app_ram_usage_description + ) + ) + put( + SwitchSetting( + BooleanSetting.SHOW_SYSTEM_RAM_USAGE, + R.string.show_system_ram_usage, + descriptionId = R.string.show_system_ram_usage_description + ) + ) + put( + SwitchSetting( + BooleanSetting.SHOW_BAT_TEMPERATURE, + R.string.show_bat_temperature, + descriptionId = R.string.show_bat_temperature_description + ) + ) put( SingleChoiceSetting( IntSetting.RENDERER_VSYNC, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index 7fa22b272f..7031d41654 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -88,6 +88,7 @@ class SettingsFragmentPresenter( MenuTag.SECTION_ROOT -> addConfigSettings(sl) MenuTag.SECTION_SYSTEM -> addSystemSettings(sl) MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl) + MenuTag.SECTION_PERFORMANCE_STATS -> addPerfomanceOverlaySettings(sl) MenuTag.SECTION_AUDIO -> addAudioSettings(sl) MenuTag.SECTION_INPUT -> addInputSettings(sl) MenuTag.SECTION_INPUT_PLAYER_ONE -> addInputPlayer(sl, 0) @@ -127,6 +128,15 @@ class SettingsFragmentPresenter( menuKey = MenuTag.SECTION_RENDERER ) ) + if (!NativeConfig.isPerGameConfigLoaded()) + add( + SubmenuSetting( + titleId = R.string.stats_overlay_options, + descriptionId = R.string.stats_overlay_options_description, + iconId = R.drawable.ic_frames, + menuKey = MenuTag.SECTION_PERFORMANCE_STATS + ) + ) add( SubmenuSetting( titleId = R.string.preferences_audio, @@ -187,6 +197,23 @@ class SettingsFragmentPresenter( } } + private fun addPerfomanceOverlaySettings(sl: ArrayList) { + sl.apply { + add(HeaderSetting(R.string.stats_overlay_customization)) + add(BooleanSetting.SHOW_PERFORMANCE_OVERLAY.key) + add(BooleanSetting.OVERLAY_BACKGROUND.key) + add(IntSetting.PERF_OVERLAY_POSITION.key) + add(HeaderSetting(R.string.stats_overlay_items)) + add(BooleanSetting.SHOW_FPS.key) + add(BooleanSetting.SHOW_FRAMETIME.key) + add(BooleanSetting.SHOW_SPEED.key) + add(BooleanSetting.SHOW_APP_RAM_USAGE.key) + add(BooleanSetting.SHOW_SYSTEM_RAM_USAGE.key) + add(BooleanSetting.SHOW_BAT_TEMPERATURE.key) + } + + } + private fun addAudioSettings(sl: ArrayList) { sl.apply { add(IntSetting.AUDIO_OUTPUT_ENGINE.key) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index 2c99f6a2ac..43997db889 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt @@ -4,18 +4,29 @@ package org.yuzu.yuzu_emu.fragments import android.annotation.SuppressLint +import android.app.ActivityManager import android.app.AlertDialog import android.content.Context import android.content.DialogInterface +import android.content.Intent +import android.content.IntentFilter import android.content.pm.ActivityInfo import android.content.res.Configuration +import android.graphics.Color import android.net.Uri +import android.os.BatteryManager import android.os.Bundle import android.os.Handler import android.os.Looper import android.os.SystemClock import android.util.Rational -import android.view.* +import android.view.Gravity +import android.view.LayoutInflater +import android.view.MotionEvent +import android.view.Surface +import android.view.SurfaceHolder +import android.view.View +import android.view.ViewGroup import android.widget.FrameLayout import android.widget.TextView import android.widget.Toast @@ -26,7 +37,6 @@ import androidx.core.graphics.Insets import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.updateLayoutParams -import androidx.core.view.updatePadding import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout.DrawerListener import androidx.fragment.app.Fragment @@ -36,6 +46,7 @@ import androidx.navigation.fragment.navArgs import androidx.window.layout.FoldingFeature import androidx.window.layout.WindowInfoTracker import androidx.window.layout.WindowLayoutInfo +import com.google.android.material.color.MaterialColors import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.slider.Slider import org.yuzu.yuzu_emu.HomeNavigationDirections @@ -51,28 +62,28 @@ import org.yuzu.yuzu_emu.features.settings.model.Settings.EmulationOrientation import org.yuzu.yuzu_emu.features.settings.model.Settings.EmulationVerticalAlignment import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile import org.yuzu.yuzu_emu.model.DriverViewModel -import org.yuzu.yuzu_emu.model.Game import org.yuzu.yuzu_emu.model.EmulationViewModel +import org.yuzu.yuzu_emu.model.Game import org.yuzu.yuzu_emu.overlay.model.OverlayControl import org.yuzu.yuzu_emu.overlay.model.OverlayLayout -import org.yuzu.yuzu_emu.utils.* +import org.yuzu.yuzu_emu.utils.DirectoryInitialization +import org.yuzu.yuzu_emu.utils.FileUtil +import org.yuzu.yuzu_emu.utils.GameHelper +import org.yuzu.yuzu_emu.utils.GameIconUtils +import org.yuzu.yuzu_emu.utils.Log +import org.yuzu.yuzu_emu.utils.NativeConfig +import org.yuzu.yuzu_emu.utils.ViewUtils import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible -import java.lang.NullPointerException -import android.content.BroadcastReceiver -import android.content.Intent -import android.content.IntentFilter -import android.os.BatteryManager -import android.util.TypedValue -import android.app.ActivityManager -import android.graphics.Color -import android.os.Debug +import org.yuzu.yuzu_emu.utils.collect +import java.io.File class EmulationFragment : Fragment(), SurfaceHolder.Callback { private lateinit var emulationState: EmulationState private var emulationActivity: EmulationActivity? = null private var perfStatsUpdater: (() -> Unit)? = null - private var thermalStatsUpdater: (() -> Unit)? = null - private var batteryReceiverRegistered: Boolean = false + private lateinit var cpuBackend: String + private lateinit var gpuDriver: String + private var _binding: FragmentEmulationBinding? = null private val binding get() = _binding!! @@ -198,8 +209,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { } }) binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) - binding.inGameMenu.getHeaderView(0).findViewById(R.id.text_game_title).text = - game.title + binding.inGameMenu.getHeaderView(0).apply { + val titleView = findViewById(R.id.text_game_title) + titleView.text = game.title + } binding.inGameMenu.menu.findItem(R.id.menu_lock_drawer).apply { val lockMode = IntSetting.LOCK_DRAWER.getInt() @@ -375,9 +388,23 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { emulationState.updateSurface() // Setup overlays - updateShowFpsOverlay() - val temperature = getBatteryTemperature(requireContext()) - updateThermalOverlay(temperature) + updateshowStatsOvelray() + + // Re update binding when the specs values get initialized properly + binding.inGameMenu.getHeaderView(0).apply { + val titleView = findViewById(R.id.text_game_title) + val cpuBackendLabel = findViewById(R.id.cpu_backend) + val gpuvendorLabel = findViewById(R.id.gpu_vendor) + + titleView.text = game.title + cpuBackendLabel.text = NativeLibrary.getCpuBackend() + gpuvendorLabel.text = NativeLibrary.getGpuDriver() + } + + + val position = IntSetting.PERF_OVERLAY_POSITION.getInt() + updateStatsPosition(position) + } } emulationViewModel.isEmulationStopping.collect(viewLifecycleOwner) { @@ -385,7 +412,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { binding.loadingText.setText(R.string.shutting_down) ViewUtils.showView(binding.loadingIndicator) ViewUtils.hideView(binding.inputContainer) - ViewUtils.hideView(binding.showFpsText) + ViewUtils.hideView(binding.showStatsOverlayText) } } emulationViewModel.drawerOpen.collect(viewLifecycleOwner) { @@ -467,22 +494,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { if (emulationState.isRunning && emulationActivity?.isInPictureInPictureMode != true) { emulationState.pause() } - context?.let { - if (batteryReceiverRegistered) { - it.unregisterReceiver(batteryReceiver) - batteryReceiverRegistered = false - } - } super.onPause() } override fun onDestroyView() { - context?.let { - if (batteryReceiverRegistered) { - it.unregisterReceiver(batteryReceiver) - batteryReceiverRegistered = false - } - } super.onDestroyView() _binding = null } @@ -492,12 +507,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { super.onDetach() } override fun onResume() { - super.onResume() - if (!batteryReceiverRegistered) { - val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED) - context?.registerReceiver(batteryReceiver, filter) - batteryReceiverRegistered = true - } + super.onResume() + // If the overlay is enabled, we need to update the position if changed + val position = IntSetting.PERF_OVERLAY_POSITION.getInt() + updateStatsPosition(position) } private fun resetInputOverlay() { @@ -508,38 +521,91 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { } } @SuppressLint("DefaultLocale") - private fun updateShowFpsOverlay() { + private fun updateshowStatsOvelray() { val showOverlay = BooleanSetting.SHOW_PERFORMANCE_OVERLAY.getBoolean() - binding.showFpsText.setTextColor(Color.parseColor("#A146FF")) - binding.showFpsText.setVisible(showOverlay) + binding.showStatsOverlayText.apply { + setTextColor( + MaterialColors.getColor( + this, + com.google.android.material.R.attr.colorPrimary + ) + ) + } + binding.showStatsOverlayText.setVisible(showOverlay) if (showOverlay) { val SYSTEM_FPS = 0 val FPS = 1 val FRAMETIME = 2 val SPEED = 3 + val sb = StringBuilder() perfStatsUpdater = { if (emulationViewModel.emulationStarted.value && !emulationViewModel.isEmulationStopping.value ) { + sb.setLength(0) // Clear the StringBuilder to avoid recurring appends + val perfStats = NativeLibrary.getPerfStats() - val cpuBackend = NativeLibrary.getCpuBackend() - val gpuDriver = NativeLibrary.getGpuDriver() - - // Get memory info - val mi = ActivityManager.MemoryInfo() - val activityManager = - requireContext().getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager - activityManager.getMemoryInfo(mi) - - // Calculate used memory - val usedMegs = (mi.totalMem - mi.availMem) / 1048576L // Convert bytes to megabytes if (_binding != null) { - binding.showFpsText.text = String.format( - "%.1f FPS • %d MB • %s/%s", - perfStats[FPS], usedMegs, cpuBackend, gpuDriver - ) + if (BooleanSetting.SHOW_FPS.getBoolean(NativeConfig.isPerGameConfigLoaded())) { + sb.append(String.format("FPS: %d", (perfStats[FPS] + 0.5).toInt())) + // perfStats[FPS], usedMegs, cpuBackend, gpuDriver + + if (BooleanSetting.SHOW_FRAMETIME.getBoolean(NativeConfig.isPerGameConfigLoaded())) { + if (sb.isNotEmpty()) sb.append(" | ") + sb.append( + String.format( + "FT: %.1fms", + (perfStats[FRAMETIME] * 1000.0f).toFloat() + ) + ) + } + + if (BooleanSetting.SHOW_SPEED.getBoolean(NativeConfig.isPerGameConfigLoaded())) { + if (sb.isNotEmpty()) sb.append(" | ") + sb.append( + String.format( + "Speed: %d%%", + (perfStats[SPEED] * 100.0 + 0.5).toInt() + ) + ) + } + + if (BooleanSetting.SHOW_APP_RAM_USAGE.getBoolean(NativeConfig.isPerGameConfigLoaded())) { + if (sb.isNotEmpty()) sb.append(" | ") + val appRamUsage = + File("/proc/self/statm").readLines()[0].split(' ')[1].toLong() * 4096 / 1000000 + sb.append("Process RAM: $appRamUsage MB") + } + + if (BooleanSetting.SHOW_SYSTEM_RAM_USAGE.getBoolean(NativeConfig.isPerGameConfigLoaded())) { + if (sb.isNotEmpty()) sb.append(" | ") + context?.let { ctx -> + val activityManager = + ctx.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + val memInfo = ActivityManager.MemoryInfo() + activityManager.getMemoryInfo(memInfo) + val usedRamMB = (memInfo.totalMem - memInfo.availMem) / 1048576L + sb.append("RAM: $usedRamMB MB") + } + } + + if (BooleanSetting.SHOW_BAT_TEMPERATURE.getBoolean(NativeConfig.isPerGameConfigLoaded())) { + if (sb.isNotEmpty()) sb.append(" | ") + val batteryTemp = getBatteryTemperature() + val tempF = celsiusToFahrenheit(batteryTemp) + sb.append(String.format("%.1f°C/%.1f°F", batteryTemp, tempF)) + } + + if (BooleanSetting.OVERLAY_BACKGROUND.getBoolean(NativeConfig.isPerGameConfigLoaded())) { + binding.showStatsOverlayText.setBackgroundResource(R.color.yuzu_transparent_black) + } else { + binding.showStatsOverlayText.setBackgroundResource(0) + } + + binding.showStatsOverlayText.text = sb.toString() } + } perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 800) } } @@ -551,47 +617,76 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { } } -private val batteryReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - intent?.let { - if (it.action == Intent.ACTION_BATTERY_CHANGED) { - val temperature = getBatteryTemperature(context!!) - updateThermalOverlay(temperature) + private fun updateStatsPosition(position: Int) { + val params = binding.showStatsOverlayText.layoutParams as FrameLayout.LayoutParams + when (position) { + 0 -> { + params.gravity = (Gravity.TOP or Gravity.START) + params.setMargins(resources.getDimensionPixelSize(R.dimen.spacing_large), 0, 0, 0) + } + + 1 -> { + params.gravity = (Gravity.TOP or Gravity.CENTER_HORIZONTAL) + } + + 2 -> { + params.gravity = (Gravity.TOP or Gravity.END) + params.setMargins(0, 0, resources.getDimensionPixelSize(R.dimen.spacing_large), 0) + } + + 3 -> { + params.gravity = (Gravity.BOTTOM or Gravity.START) + params.setMargins(resources.getDimensionPixelSize(R.dimen.spacing_large), 0, 0, 0) + } + + 4 -> { + params.gravity = (Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL) + } + + 5 -> { + params.gravity = (Gravity.BOTTOM or Gravity.END) + params.setMargins(0, 0, resources.getDimensionPixelSize(R.dimen.spacing_large), 0) } } } -} -private fun updateThermalOverlay(temperature: Float) { - if (BooleanSetting.SHOW_THERMAL_OVERLAY.getBoolean() && - emulationViewModel.emulationStarted.value && - !emulationViewModel.isEmulationStopping.value - ) { - // Convert to Fahrenheit - val fahrenheit = (temperature * 9f / 5f) + 32f - - // Determine color based on temperature ranges - val color = when { - temperature < 35 -> Color.parseColor("#00C8FF") - temperature < 40 -> Color.parseColor("#A146FF") - temperature < 45 -> Color.parseColor("#FFA500") - else -> Color.RED + private fun getBatteryTemperature(): Float { + try { + val batteryIntent = requireContext().registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) + // Temperature in tenths of a degree Celsius + val temperature = batteryIntent?.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0) ?: 0 + // Convert to degrees Celsius + return temperature / 10.0f + } catch (e: Exception) { + return 0.0f } - - binding.showThermalsText.setTextColor(color) - binding.showThermalsText.text = String.format("%.1f°C • %.1f°F", temperature, fahrenheit) } -} - -private fun getBatteryTemperature(context: Context): Float { - val intent: Intent? = context.registerReceiver( - null, - IntentFilter(Intent.ACTION_BATTERY_CHANGED) - ) - val temperature = intent?.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0) ?: 0 - return temperature / 10.0f + private fun celsiusToFahrenheit(celsius: Float): Float { + return (celsius * 9 / 5) + 32 } + private fun updateThermalOverlay(temperature: Float) { + if (BooleanSetting.SHOW_THERMAL_OVERLAY.getBoolean() && + emulationViewModel.emulationStarted.value && + !emulationViewModel.isEmulationStopping.value + ) { + // Convert to Fahrenheit + val fahrenheit = (temperature * 9f / 5f) + 32f + + // Determine color based on temperature ranges + val color = when { + temperature < 35 -> Color.parseColor("#00C8FF") + temperature < 40 -> Color.parseColor("#A146FF") + temperature < 45 -> Color.parseColor("#FFA500") + else -> Color.RED + } + + binding.showThermalsText.setTextColor(color) + binding.showThermalsText.text = String.format("%.1f°C • %.1f°F", temperature, fahrenheit) + } + } + + @SuppressLint("SourceLockedOrientationActivity") private fun updateOrientation() { emulationActivity?.let { @@ -717,10 +812,8 @@ private fun getBatteryTemperature(context: Context): Float { popup.menuInflater.inflate(R.menu.menu_overlay_options, popup.menu) popup.menu.apply { - findItem(R.id.menu_toggle_fps).isChecked = + findItem(R.id.menu_show_stats_overlay).isChecked = BooleanSetting.SHOW_PERFORMANCE_OVERLAY.getBoolean() - findItem(R.id.thermal_indicator).isChecked = - BooleanSetting.SHOW_THERMAL_OVERLAY.getBoolean() findItem(R.id.menu_rel_stick_center).isChecked = BooleanSetting.JOYSTICK_REL_CENTER.getBoolean() findItem(R.id.menu_dpad_slide).isChecked = BooleanSetting.DPAD_SLIDE.getBoolean() @@ -733,34 +826,12 @@ private fun getBatteryTemperature(context: Context): Float { popup.setOnDismissListener { NativeConfig.saveGlobalConfig() } popup.setOnMenuItemClickListener { when (it.itemId) { - R.id.menu_toggle_fps -> { + R.id.menu_show_stats_overlay -> { it.isChecked = !it.isChecked BooleanSetting.SHOW_PERFORMANCE_OVERLAY.setBoolean(it.isChecked) - updateShowFpsOverlay() + updateshowStatsOvelray() true } - - R.id.thermal_indicator -> { - it.isChecked = !it.isChecked - BooleanSetting.SHOW_THERMAL_OVERLAY.setBoolean(it.isChecked) - if (it.isChecked) { - val temperature = getBatteryTemperature(requireContext()) - updateThermalOverlay(temperature) - if (!batteryReceiverRegistered) { - val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED) - context?.registerReceiver(batteryReceiver, filter) - batteryReceiverRegistered = true - } - } else { - if (batteryReceiverRegistered) { - context?.unregisterReceiver(batteryReceiver) - batteryReceiverRegistered = false - } - binding.showThermalsText.text = "" - } - true - } - R.id.menu_edit_overlay -> { binding.drawerLayout.close() binding.surfaceInputOverlay.requestFocus() @@ -951,7 +1022,8 @@ private fun getBatteryTemperature(context: Context): Float { right = cutInsets.right } - v.updatePadding(left = left, top = cutInsets.top, right = right) + v.setPadding(left, cutInsets.top, right, 0) + windowInsets } } diff --git a/src/android/app/src/main/jni/android_settings.h b/src/android/app/src/main/jni/android_settings.h index 00baf86a9b..a47803604a 100644 --- a/src/android/app/src/main/jni/android_settings.h +++ b/src/android/app/src/main/jni/android_settings.h @@ -66,9 +66,23 @@ struct Values { Settings::Setting haptic_feedback{linkage, true, "haptic_feedback", Settings::Category::Overlay}; Settings::Setting show_performance_overlay{linkage, true, "show_performance_overlay", - Settings::Category::Overlay}; - Settings::Setting show_thermal_overlay{linkage, false, "show_thermal_overlay", - Settings::Category::Overlay}; + Settings::Category::Overlay, Settings::Specialization::Paired, true , true}; + Settings::Setting overlay_background{linkage, false, "overlay_background", + Settings::Category::Overlay, Settings::Specialization::Default, true , true, &show_performance_overlay}; + Settings::Setting perf_overlay_position{linkage, 0, "perf_overlay_position", + Settings::Category::Overlay, Settings::Specialization::Default, true , true, &show_performance_overlay}; + Settings::Setting show_fps{linkage, true, "show_fps", + Settings::Category::Overlay, Settings::Specialization::Default, true , true, &show_performance_overlay}; + Settings::Setting show_frame_time{linkage, false, "show_frame_time", + Settings::Category::Overlay, Settings::Specialization::Default, true , true, &show_performance_overlay}; + Settings::Setting show_speed{linkage, true, "show_speed", + Settings::Category::Overlay, Settings::Specialization::Default, true , true, &show_performance_overlay}; + Settings::Setting show_app_ram_usage{linkage, false, "show_app_ram_usage", + Settings::Category::Overlay, Settings::Specialization::Default, true , true, &show_performance_overlay}; + Settings::Setting show_system_ram_usage{linkage, false, "show_system_ram_usage", + Settings::Category::Overlay, Settings::Specialization::Default, true , true, &show_performance_overlay}; + Settings::Setting show_bat_temperature{linkage, false, "show_bat_temperature", + Settings::Category::Overlay, Settings::Specialization::Default, true , true, &show_performance_overlay}; Settings::Setting show_input_overlay{linkage, true, "show_input_overlay", Settings::Category::Overlay}; Settings::Setting touchscreen{linkage, true, "touchscreen", Settings::Category::Overlay}; diff --git a/src/android/app/src/main/res/drawable/ic_frames.xml b/src/android/app/src/main/res/drawable/ic_frames.xml new file mode 100644 index 0000000000..aee24007b0 --- /dev/null +++ b/src/android/app/src/main/res/drawable/ic_frames.xml @@ -0,0 +1,32 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/android/app/src/main/res/layout/fragment_emulation.xml b/src/android/app/src/main/res/layout/fragment_emulation.xml index 185ad37814..00f2cdc103 100644 --- a/src/android/app/src/main/res/layout/fragment_emulation.xml +++ b/src/android/app/src/main/res/layout/fragment_emulation.xml @@ -140,15 +140,13 @@ android:id="@+id/overlay_container" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_marginHorizontal="20dp" - android:fitsSystemWindows="true"> + android:fitsSystemWindows="false"> - + android:layout_marginEnd="24dp"> + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/android/app/src/main/res/menu/menu_overlay_options.xml b/src/android/app/src/main/res/menu/menu_overlay_options.xml index a9e807427b..3315dbfdc9 100644 --- a/src/android/app/src/main/res/menu/menu_overlay_options.xml +++ b/src/android/app/src/main/res/menu/menu_overlay_options.xml @@ -2,13 +2,8 @@ - - #B7B7B7 + #80000000 #C6C5D0 #FFB4AB #93000A diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 99013e0485..318baacf09 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -183,6 +183,23 @@ 2 + + @string/overlay_position_top_left + @string/overlay_position_center_top + @string/overlay_position_top_right + @string/overlay_position_bottom_left + @string/overlay_position_center_bottom + @string/overlay_position_bottom_right + + + 0 + 1 + 2 + 3 + 4 + 5 + + @string/cpu_backend_dynarmic @string/cpu_backend_nce diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index bb0b5c58dc..3606ff9d2a 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -9,6 +9,37 @@ Shows notifications when something goes wrong. Notification permission not granted! + + ShoW Performance Stats Overlay + Customization + Visibility + Overlay + Enable Performance Stats Overlay + Configure what information is shown in the performance stats overlay + Show FPS + Display current frames per second + Show Frametime + Display current frametime + Show Speed + Display current emulation speed percentage + Show App Memory Usage + Display the amount of RAM getting used by the emulator + Show System Memory Usage + Display the amount of RAM getting used by the system + Show Battery Temperature + Display current Battery temperature in Celsius and Fahrenheit + Overlay Position + Choose where the performance stats overlay is displayed on the screen + Top Left + Top Right + Bottom Left + Bottom Right + Center Top + Center Bottom + Overlay Background + Adds a background behind the overlay for easier reading + + Welcome! Learn how to setup <b>eden</b> and jump into emulation. diff --git a/src/android/app/src/main/res/values/yuzu_colors.xml b/src/android/app/src/main/res/values/yuzu_colors.xml index a45b95f85c..a5af0886a9 100644 --- a/src/android/app/src/main/res/values/yuzu_colors.xml +++ b/src/android/app/src/main/res/values/yuzu_colors.xml @@ -229,6 +229,7 @@ #410002 #000000 #000000 + #80000000 #FFFFFF #FFFFFF