summaryrefslogtreecommitdiff
path: root/src/android
diff options
context:
space:
mode:
Diffstat (limited to 'src/android')
-rw-r--r--src/android/app/src/main/java/org/citron/citron_emu/features/settings/model/BooleanSetting.kt2
-rw-r--r--src/android/app/src/main/java/org/citron/citron_emu/fragments/EmulationFragment.kt91
-rw-r--r--src/android/app/src/main/jni/android_settings.h7
-rw-r--r--src/android/app/src/main/res/layout/fragment_emulation.xml15
-rw-r--r--src/android/app/src/main/res/menu/menu_overlay_options.xml5
-rw-r--r--src/android/app/src/main/res/values/strings.xml1
6 files changed, 95 insertions, 26 deletions
diff --git a/src/android/app/src/main/java/org/citron/citron_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/citron/citron_emu/features/settings/model/BooleanSetting.kt
index 895194db5..f781d10c1 100644
--- a/src/android/app/src/main/java/org/citron/citron_emu/features/settings/model/BooleanSetting.kt
+++ b/src/android/app/src/main/java/org/citron/citron_emu/features/settings/model/BooleanSetting.kt
@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-FileCopyrightText: 2025 Citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.citron.citron_emu.features.settings.model
@@ -27,6 +28,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
SHOW_INPUT_OVERLAY("show_input_overlay"),
TOUCHSCREEN("touchscreen"),
SHOW_THERMAL_OVERLAY("show_thermal_overlay"),
+ SHOW_RAM_OVERLAY("show_ram_overlay"),
USE_AUTO_STUB("use_auto_stub");
override fun getBoolean(needsGlobal: Boolean): Boolean =
diff --git a/src/android/app/src/main/java/org/citron/citron_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/citron/citron_emu/fragments/EmulationFragment.kt
index 93a15def9..f4678b603 100644
--- a/src/android/app/src/main/java/org/citron/citron_emu/fragments/EmulationFragment.kt
+++ b/src/android/app/src/main/java/org/citron/citron_emu/fragments/EmulationFragment.kt
@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-FileCopyrightText: 2025 Citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.citron.citron_emu.fragments
@@ -11,9 +12,11 @@ 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.Debug
import android.os.Handler
import android.os.Looper
import android.os.PowerManager
@@ -68,6 +71,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
private var emulationActivity: EmulationActivity? = null
private var perfStatsUpdater: (() -> Unit)? = null
private var thermalStatsUpdater: (() -> Unit)? = null
+ private var ramStatsUpdater: (() -> Unit)? = null
private var _binding: FragmentEmulationBinding? = null
private val binding get() = _binding!!
@@ -83,6 +87,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
private lateinit var powerManager: PowerManager
+ private val ramStatsUpdateHandler = Handler(Looper.myLooper()!!)
+
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is EmulationActivity) {
@@ -376,6 +382,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
// Setup overlays
updateShowFpsOverlay()
updateThermalOverlay()
+ updateRamOverlay()
}
}
emulationViewModel.isEmulationStopping.collect(viewLifecycleOwner) {
@@ -470,6 +477,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
override fun onDestroyView() {
super.onDestroyView()
+ if (ramStatsUpdater != null) {
+ ramStatsUpdateHandler.removeCallbacks(ramStatsUpdater!!)
+ }
_binding = null
}
@@ -552,8 +562,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
emulationViewModel.emulationStarted.value &&
!emulationViewModel.isEmulationStopping.value
) {
- // Get thermal status
+ // Get thermal status for color
val thermalStatus = when (powerManager.currentThermalStatus) {
+ PowerManager.THERMAL_STATUS_NONE -> 0f
PowerManager.THERMAL_STATUS_LIGHT -> 0.25f
PowerManager.THERMAL_STATUS_MODERATE -> 0.5f
PowerManager.THERMAL_STATUS_SEVERE -> 0.75f
@@ -563,34 +574,57 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
else -> 0f
}
- // Convert to Fahrenheit for additional info
+ // Convert to Fahrenheit
val fahrenheit = (temperature * 9f / 5f) + 32f
- // Create progress bar using block elements
- val progressBarLength = 12
- val filledBars = (thermalStatus * progressBarLength).toInt()
- val progressBar = buildString {
- append("│") // Left border
- repeat(filledBars) { append("█") }
- repeat(progressBarLength - filledBars) { append("░") }
- append("│") // Right border
- append(" ")
- append(String.format("%3d%%", (thermalStatus * 100).toInt()))
- }
-
- // Color interpolation based on temperature (green at 30°C, red at 45°C)
- val normalizedTemp = ((temperature - 30f) / 15f).coerceIn(0f, 1f)
- val red = (normalizedTemp * 255).toInt()
- val green = ((1f - normalizedTemp) * 255).toInt()
+ // Color based on thermal status (green to red)
+ val red = (thermalStatus * 255).toInt()
+ val green = ((1f - thermalStatus) * 255).toInt()
val color = android.graphics.Color.rgb(red, green, 0)
binding.showThermalsText.setTextColor(color)
- binding.showThermalsText.text = String.format(
- "%s\n%.1f°C • %.1f°F",
- progressBar,
- temperature,
- fahrenheit
- )
+ binding.showThermalsText.text = String.format("%.1f°C • %.1f°F", temperature, fahrenheit)
+ }
+ }
+
+ private fun updateRamOverlay() {
+ val showOverlay = BooleanSetting.SHOW_RAM_OVERLAY.getBoolean()
+ binding.showRamText.setVisible(showOverlay)
+ if (showOverlay) {
+ ramStatsUpdater = {
+ if (emulationViewModel.emulationStarted.value &&
+ !emulationViewModel.isEmulationStopping.value
+ ) {
+ val runtime = Runtime.getRuntime()
+ val nativeHeapSize = Debug.getNativeHeapSize()
+ val nativeHeapFreeSize = Debug.getNativeHeapFreeSize()
+ val nativeHeapUsed = nativeHeapSize - nativeHeapFreeSize
+
+ val usedMemInMB = nativeHeapUsed / 1048576L
+ val maxMemInMB = nativeHeapSize / 1048576L
+ val percentUsed = (nativeHeapUsed.toFloat() / nativeHeapSize.toFloat() * 100f)
+
+ // Color interpolation from green to red based on usage percentage
+ val normalizedUsage = (percentUsed / 100f).coerceIn(0f, 1f)
+ val red = (normalizedUsage * 255).toInt()
+ val green = ((1f - normalizedUsage) * 255).toInt()
+ val color = Color.rgb(red, green, 0)
+
+ binding.showRamText.setTextColor(color)
+ binding.showRamText.text = String.format(
+ "\nRAM: %d/%d MB (%.1f%%)",
+ usedMemInMB,
+ maxMemInMB,
+ percentUsed
+ )
+ ramStatsUpdateHandler.postDelayed(ramStatsUpdater!!, 1000)
+ }
+ }
+ ramStatsUpdateHandler.post(ramStatsUpdater!!)
+ } else {
+ if (ramStatsUpdater != null) {
+ ramStatsUpdateHandler.removeCallbacks(ramStatsUpdater!!)
+ }
}
}
@@ -723,6 +757,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
BooleanSetting.SHOW_PERFORMANCE_OVERLAY.getBoolean()
findItem(R.id.thermal_indicator).isChecked =
BooleanSetting.SHOW_THERMAL_OVERLAY.getBoolean()
+ findItem(R.id.ram_meter).apply {
+ isChecked = BooleanSetting.SHOW_RAM_OVERLAY.getBoolean()
+ isEnabled = false // This grays out the option
+ }
findItem(R.id.menu_rel_stick_center).isChecked =
BooleanSetting.JOYSTICK_REL_CENTER.getBoolean()
findItem(R.id.menu_dpad_slide).isChecked = BooleanSetting.DPAD_SLIDE.getBoolean()
@@ -749,6 +787,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
true
}
+ R.id.ram_meter -> {
+ // Do nothing since it's disabled
+ true
+ }
+
R.id.menu_edit_overlay -> {
binding.drawerLayout.close()
binding.surfaceInputOverlay.requestFocus()
diff --git a/src/android/app/src/main/jni/android_settings.h b/src/android/app/src/main/jni/android_settings.h
index 00baf86a9..2dba36990 100644
--- a/src/android/app/src/main/jni/android_settings.h
+++ b/src/android/app/src/main/jni/android_settings.h
@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-FileCopyrightText: 2025 Citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -51,7 +52,7 @@ struct Values {
Settings::Setting<s32> theme{linkage, 0, "theme", Settings::Category::Android};
Settings::Setting<s32> theme_mode{linkage, -1, "theme_mode", Settings::Category::Android};
- Settings::Setting<bool> black_backgrounds{linkage, false, "black_backgrounds",
+ Settings::Setting<bool> black_backgrounds{linkage, true, "black_backgrounds",
Settings::Category::Android};
// Input/performance overlay settings
@@ -67,8 +68,10 @@ struct Values {
Settings::Category::Overlay};
Settings::Setting<bool> show_performance_overlay{linkage, true, "show_performance_overlay",
Settings::Category::Overlay};
- Settings::Setting<bool> show_thermal_overlay{linkage, false, "show_thermal_overlay",
+ Settings::Setting<bool> show_thermal_overlay{linkage, true, "show_thermal_overlay",
Settings::Category::Overlay};
+ Settings::Setting<bool> show_ram_overlay{linkage, true, "show_ram_overlay",
+ Settings::Category::Overlay};
Settings::Setting<bool> show_input_overlay{linkage, true, "show_input_overlay",
Settings::Category::Overlay};
Settings::Setting<bool> touchscreen{linkage, true, "touchscreen", Settings::Category::Overlay};
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 df91a08c5..fe028e028 100644
--- a/src/android/app/src/main/res/layout/fragment_emulation.xml
+++ b/src/android/app/src/main/res/layout/fragment_emulation.xml
@@ -171,6 +171,21 @@
</FrameLayout>
+ <com.google.android.material.textview.MaterialTextView
+ android:id="@+id/show_ram_text"
+ style="@style/TextAppearance.Material3.BodySmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:layout_marginTop="24dp"
+ android:clickable="false"
+ android:focusable="false"
+ android:textColor="@android:color/white"
+ android:shadowColor="@android:color/black"
+ android:shadowRadius="3"
+ android:layout_below="@id/show_fps_text"
+ tools:ignore="RtlHardcoded" />
+
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
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 a9e807427..d601421a7 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
@@ -12,6 +12,11 @@
android:checkable="true" />
<item
+ android:id="@+id/ram_meter"
+ android:title="@string/emulation_ram_meter"
+ android:checkable="true" />
+
+ <item
android:id="@+id/menu_edit_overlay"
android:title="@string/emulation_touch_overlay_edit" />
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 5133fa98e..ce2b21bf1 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -480,6 +480,7 @@
<string name="emulation_done">Done</string>
<string name="emulation_fps_counter">FPS counter</string>
<string name="emulation_thermal_indicator">Thermal indicator</string>
+ <string name="emulation_ram_meter">RAM meter</string>
<string name="emulation_toggle_controls">Toggle controls</string>
<string name="emulation_rel_stick_center">Relative stick center</string>
<string name="emulation_dpad_slide">D-pad slide</string>