diff --git a/CMakeLists.txt b/CMakeLists.txt index 30c29117b..a9c0e1a25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,23 +97,7 @@ if (ANDROID OR WIN32 OR APPLE) endif() option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL}) -if (ANDROID AND CITRON_DOWNLOAD_ANDROID_VVL) - set(vvl_version "sdk-1.3.261.1") - set(vvl_zip_file "${CMAKE_BINARY_DIR}/externals/vvl-android.zip") - if (NOT EXISTS "${vvl_zip_file}") - # Download and extract validation layer release to externals directory - set(vvl_base_url "https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases/download") - file(DOWNLOAD "${vvl_base_url}/${vvl_version}/android-binaries-${vvl_version}-android.zip" - "${vvl_zip_file}" SHOW_PROGRESS) - execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${vvl_zip_file}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals") - endif() - - # Copy the arm64 binary to src/android/app/main/jniLibs - set(vvl_lib_path "${CMAKE_CURRENT_SOURCE_DIR}/src/android/app/src/main/jniLibs/arm64-v8a/") - file(COPY "${CMAKE_BINARY_DIR}/externals/android-binaries-${vvl_version}/arm64-v8a/libVkLayer_khronos_validation.so" - DESTINATION "${vvl_lib_path}") -endif() +# Copy the VVL arm64 binary to src/android/app/main/jniLibs. REF: https://github.com/KhronosGroup/Vulkan-ValidationLayers/actions/workflows/vvl.yml if (ANDROID) set(CMAKE_SKIP_INSTALL_RULES ON) diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index 793a8621c..35b2948ad 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -10,10 +10,10 @@ plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("kotlin-parcelize") - kotlin("plugin.serialization") version "2.1.20-Beta1" + kotlin("plugin.serialization") version "1.9.20" id("androidx.navigation.safeargs.kotlin") - id("org.jlleitschuh.gradle.ktlint") version "12.1.2" - id("com.github.triplet.play") version "3.12.1" + id("org.jlleitschuh.gradle.ktlint") version "11.4.0" + id("com.github.triplet.play") version "3.8.6" } /** @@ -180,7 +180,7 @@ android { "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON" ) - abiFilters("arm64-v8a", "x86_64") + abiFilters("arm64-v8a") } } } @@ -226,24 +226,23 @@ play { } dependencies { - implementation("androidx.core:core-ktx:1.15.0") - implementation("androidx.appcompat:appcompat:1.7.0") - implementation("androidx.recyclerview:recyclerview:1.3.2") - implementation("androidx.constraintlayout:constraintlayout:2.2.0") - implementation("androidx.fragment:fragment-ktx:1.8.5") + implementation("androidx.core:core-ktx:1.12.0") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("androidx.recyclerview:recyclerview:1.3.1") + implementation("androidx.constraintlayout:constraintlayout:2.1.4") + implementation("androidx.fragment:fragment-ktx:1.6.1") implementation("androidx.documentfile:documentfile:1.0.1") - implementation("com.google.android.material:material:1.12.0") + implementation("com.google.android.material:material:1.9.0") implementation("androidx.preference:preference-ktx:1.2.1") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2") implementation("io.coil-kt:coil:2.2.2") implementation("androidx.core:core-splashscreen:1.0.1") - implementation("androidx.window:window:1.3.0") - implementation("androidx.constraintlayout:constraintlayout:2.2.0") + implementation("androidx.window:window:1.2.0-beta03") implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") - implementation("androidx.navigation:navigation-fragment-ktx:2.8.5") - implementation("androidx.navigation:navigation-ui-ktx:2.8.5") + implementation("androidx.navigation:navigation-fragment-ktx:2.7.4") + implementation("androidx.navigation:navigation-ui-ktx:2.7.4") implementation("info.debatty:java-string-similarity:2.0.0") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") } fun runGitCommand(command: List): String { 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 aa255a942..58d176e92 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 @@ -499,10 +499,20 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { val cpuBackend = NativeLibrary.getCpuBackend() val gpuDriver = NativeLibrary.getGpuDriver() if (_binding != null) { + // Calculate color based on FPS (red at 0, green at 60) + val fps = perfStats[FPS].toFloat() + val normalizedFps = (fps / 60f).coerceIn(0f, 1f) + + // Interpolate between red (0xFFFF0000) and green (0xFF00FF00) + val red = ((1f - normalizedFps) * 255).toInt() + val green = (normalizedFps * 255).toInt() + val color = android.graphics.Color.rgb(red, green, 0) + + binding.showFpsText.setTextColor(color) binding.showFpsText.text = - String.format("FPS: %.1f\n%s/%s", perfStats[FPS], cpuBackend, gpuDriver) + String.format("FPS: %.1f\n%s/%s", fps, cpuBackend, gpuDriver) } - perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 800) + perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 1000) } } perfStatsUpdateHandler.post(perfStatsUpdater!!) @@ -528,11 +538,37 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { PowerManager.THERMAL_STATUS_CRITICAL, PowerManager.THERMAL_STATUS_EMERGENCY, PowerManager.THERMAL_STATUS_SHUTDOWN -> "☢️" - else -> "🙂" } + + // Get temperature in Celsius from thermal sensor + val temperature = try { + val process = Runtime.getRuntime().exec("cat /sys/class/thermal/thermal_zone0/temp") + val reader = process.inputStream.bufferedReader() + val temp = reader.readLine().toFloat() / 1000f // Convert from millicelsius to celsius + reader.close() + temp + } catch (e: Exception) { + 0f + } + + // Convert to Fahrenheit + val fahrenheit = (temperature * 9f / 5f) + 32f + if (_binding != null) { - binding.showThermalsText.text = thermalStatus + // Color interpolation based on temperature (green at 45°C, red at 85°C) + val normalizedTemp = ((temperature - 45f) / 40f).coerceIn(0f, 1f) + val red = (normalizedTemp * 255).toInt() + val green = ((1f - normalizedTemp) * 255).toInt() + val color = android.graphics.Color.rgb(red, green, 0) + + binding.showThermalsText.setTextColor(color) + binding.showThermalsText.text = String.format( + "%s %.1f°C\n%.1f°F", + thermalStatus, + temperature, + fahrenheit + ) } thermalStatsUpdateHandler.postDelayed(thermalStatsUpdater!!, 1000) } diff --git a/src/android/app/src/main/java/org/citron/citron_emu/fragments/SetupFragment.kt b/src/android/app/src/main/java/org/citron/citron_emu/fragments/SetupFragment.kt index 817210d48..7731b7608 100644 --- a/src/android/app/src/main/java/org/citron/citron_emu/fragments/SetupFragment.kt +++ b/src/android/app/src/main/java/org/citron/citron_emu/fragments/SetupFragment.kt @@ -98,6 +98,19 @@ class SetupFragment : Fragment() { val pages = mutableListOf() pages.apply { + add( + SetupPage( + R.drawable.ic_check, + R.string.disclaimer_title, + R.string.disclaimer_description, + 0, + true, + R.string.accept_and_continue, + { pageForward() }, + false + ) + ) + add( SetupPage( R.drawable.ic_citron_title, diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index bc8f42292..5b8fc30c4 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -13,6 +13,9 @@ Welcome! Learn how to setup <b>citron</b> and jump into emulation. Get started + Legal Disclaimer + Welcome to Citron! This application is intended for homebrew development and legitimate backup purposes only. We do not support or advocate piracy. By continuing, you acknowledge that you will only use this application in compliance with all applicable laws and regulations. + Accept & Continue Keys Select your <b>prod.keys</b> file with the button below. Select Keys diff --git a/src/android/build.gradle.kts b/src/android/build.gradle.kts index 2f993b197..19391b0e3 100644 --- a/src/android/build.gradle.kts +++ b/src/android/build.gradle.kts @@ -5,7 +5,7 @@ plugins { id("com.android.application") version "8.8.0" apply false id("com.android.library") version "8.8.0" apply false - id("org.jetbrains.kotlin.android") version "2.1.20-Beta1" apply false + id("org.jetbrains.kotlin.android") version "1.9.20" apply false } tasks.register("clean").configure { @@ -17,6 +17,6 @@ buildscript { google() } dependencies { - classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.8.5") + classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.6.0") } }