diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index c71cc5536..2e7032bdb 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -11,10 +11,10 @@ plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("kotlin-parcelize") - kotlin("plugin.serialization") version "1.9.20" + kotlin("plugin.serialization") version "2.1.20-RC2" id("androidx.navigation.safeargs.kotlin") - id("org.jlleitschuh.gradle.ktlint") version "11.4.0" - id("com.github.triplet.play") version "3.8.6" + id("org.jlleitschuh.gradle.ktlint") version "12.2.0" + id("com.github.triplet.play") version "3.12.1" } /** @@ -29,19 +29,19 @@ android { namespace = "org.citron.citron_emu" compileSdkVersion = "android-35" - ndkVersion = "26.1.10909125" + ndkVersion = "29.0.13113456 rc1" // "26.1.10909125" buildFeatures { viewBinding = true } compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } kotlinOptions { - jvmTarget = "17" + jvmTarget = "21" } packaging { @@ -55,7 +55,7 @@ android { defaultConfig { // TODO If this is ever modified, change application_id in strings.xml - applicationId = "org.citron.citron_emu" + applicationId = "com.antutu.ABenchMark" minSdk = 30 //noinspection EditedTargetSdkVersion targetSdk = 35 @@ -161,7 +161,7 @@ android { externalNativeBuild { cmake { - version = "3.22.1" + version = "3.31.6" path = file("../../../CMakeLists.txt") } } @@ -182,7 +182,7 @@ android { "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" ) - abiFilters("arm64-v8a", "x86_64") + abiFilters("arm64-v8a") // , "x86_64") } } } @@ -203,7 +203,7 @@ tasks.getByPath("ktlintMainSourceSetCheck").doFirst { showFormatHelp.invoke() } tasks.getByPath("loadKtlintReporters").dependsOn("ktlintReset") ktlint { - version.set("0.47.1") + version.set("0.49.1") android.set(true) ignoreFailures.set(false) disabledRules.set( @@ -228,24 +228,24 @@ play { } dependencies { - 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.core:core-ktx:1.15.0") + implementation("androidx.appcompat:appcompat:1.7.0") + implementation("androidx.recyclerview:recyclerview:1.4.0") + implementation("androidx.constraintlayout:constraintlayout:2.2.1") + implementation("androidx.fragment:fragment-ktx:1.8.6") implementation("androidx.documentfile:documentfile:1.0.1") - implementation("com.google.android.material:material:1.9.0") + implementation("com.google.android.material:material:1.12.0") implementation("androidx.preference:preference-ktx:1.2.1") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2") - implementation("io.coil-kt:coil:2.2.2") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7") + implementation("io.coil-kt:coil:2.7.0") implementation("androidx.core:core-splashscreen:1.0.1") - implementation("androidx.window:window:1.2.0-beta03") - implementation("androidx.constraintlayout:constraintlayout:2.1.4") + implementation("androidx.window:window:1.3.0") + implementation("androidx.constraintlayout:constraintlayout:2.2.1") implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") - implementation("androidx.navigation:navigation-fragment-ktx:2.7.4") - implementation("androidx.navigation:navigation-ui-ktx:2.7.4") + implementation("androidx.navigation:navigation-fragment-ktx:2.8.8") + implementation("androidx.navigation:navigation-ui-ktx:2.8.8") implementation("info.debatty:java-string-similarity:2.0.0") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3") } fun runGitCommand(command: List): String { diff --git a/src/android/build.gradle.kts b/src/android/build.gradle.kts index b77906ed6..128514ccf 100644 --- a/src/android/build.gradle.kts +++ b/src/android/build.gradle.kts @@ -1,11 +1,12 @@ // SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-FileCopyrightText: 2025 citron Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id("com.android.application") version "8.1.2" apply false - id("com.android.library") version "8.1.2" apply false - id("org.jetbrains.kotlin.android") version "1.9.20" apply false + id("com.android.application") version "8.9.0" apply false + id("com.android.library") version "8.9.0" apply false + id("org.jetbrains.kotlin.android") version "2.1.20-RC2" apply false } tasks.register("clean").configure { @@ -17,6 +18,6 @@ buildscript { google() } dependencies { - classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.6.0") + classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.8.8") } } diff --git a/src/android/gradle.properties b/src/android/gradle.properties index 4fca1b576..bdfa9430e 100644 --- a/src/android/gradle.properties +++ b/src/android/gradle.properties @@ -1,20 +1,19 @@ -# SPDX-FileCopyrightText: 2023 yuzu Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later - -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit +## For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html +# # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xms512m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +# Default value: -Xmx1024m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +# +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. For more details, visit +# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects +# org.gradle.parallel=true +#Tue Mar 11 19:29:10 AEST 2025 +android.defaults.buildfeatures.buildconfig=true +android.suppressUnsupportedCompileSdk=34 android.useAndroidX=true -# Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official kotlin.parallel.tasks.in.project=true -android.defaults.buildfeatures.buildconfig=true - -# Android Gradle plugin 8.0.2 -android.suppressUnsupportedCompileSdk=34 +org.gradle.jvmargs=-Xms512m -Dkotlin.daemon.jvm.options\="-Xmx2048M" -Xmx2048M -XX\:MaxMetaspaceSize\=512m -XX\:+HeapDumpOnOutOfMemoryError -Dfile.encoding\=UTF-8 diff --git a/src/android/gradle/wrapper/gradle-wrapper.properties b/src/android/gradle/wrapper/gradle-wrapper.properties index df97d72b8..e2847c820 100644 --- a/src/android/gradle/wrapper/gradle-wrapper.properties +++ b/src/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/common/android/android_common.h b/src/common/android/android_common.h index f0bdf62a7..8ccd4c2b0 100644 --- a/src/common/android/android_common.h +++ b/src/common/android/android_common.h @@ -1,9 +1,11 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include +#include #include #include "common/common_types.h" diff --git a/src/core/arm/nce/arm_nce.cpp b/src/core/arm/nce/arm_nce.cpp index 491edd9f9..9143928a9 100644 --- a/src/core/arm/nce/arm_nce.cpp +++ b/src/core/arm/nce/arm_nce.cpp @@ -1,5 +1,4 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -144,55 +143,30 @@ bool ArmNce::HandleGuestAlignmentFault(GuestContext* guest_ctx, void* raw_info, auto* fpctx = GetFloatingPointState(host_ctx); auto& memory = guest_ctx->system->ApplicationMemory(); - // Log the alignment fault for debugging - LOG_DEBUG(Core_ARM, "Alignment fault at PC={:X}", host_ctx.pc); - - // Try to handle the instruction + // Match and execute an instruction. auto next_pc = MatchAndExecuteOneInstruction(memory, &host_ctx, fpctx); if (next_pc) { host_ctx.pc = *next_pc; return true; } - // If we couldn't handle it, try to skip the instruction as a fallback - LOG_DEBUG(Core_ARM, "Could not handle alignment fault, skipping instruction"); - host_ctx.pc += 4; // Skip to next instruction - - // Return true to continue execution - return true; + // We couldn't handle the access. + return HandleFailedGuestFault(guest_ctx, raw_info, raw_context); } bool ArmNce::HandleGuestAccessFault(GuestContext* guest_ctx, void* raw_info, void* raw_context) { auto* info = static_cast(raw_info); - const u64 fault_addr = reinterpret_cast(info->si_addr); - auto& memory = guest_ctx->system->ApplicationMemory(); - // Get the ArmNce instance from the guest context - ArmNce* nce = guest_ctx->parent; - - // Check TLB first - if (TlbEntry* entry = nce->FindTlbEntry(fault_addr)) { - if (!entry->writable && info->si_code == SEGV_ACCERR) { - LOG_DEBUG(Core_ARM, "Write to read-only memory at {:X}", fault_addr); - return HandleFailedGuestFault(guest_ctx, raw_info, raw_context); - } + // Try to handle an invalid access. + // TODO: handle accesses which split a page? + const Common::ProcessAddress addr = + (reinterpret_cast(info->si_addr) & ~Memory::CITRON_PAGEMASK); + if (guest_ctx->system->ApplicationMemory().InvalidateNCE(addr, Memory::CITRON_PAGESIZE)) { + // We handled the access successfully and are returning to guest code. return true; } - // TLB miss handling with better error checking - if (memory.InvalidateNCE(fault_addr, Memory::CITRON_PAGESIZE)) { - const u64 host_addr = reinterpret_cast(memory.GetPointer(fault_addr)); - - if (host_addr) { - nce->AddTlbEntry(fault_addr, host_addr, Memory::CITRON_PAGESIZE, true); - return true; - } else { - LOG_DEBUG(Core_ARM, "Failed to get host address for guest address {:X}", fault_addr); - } - } else { - LOG_DEBUG(Core_ARM, "Memory invalidation failed for address {:X}", fault_addr); - } - + // We couldn't handle the access. return HandleFailedGuestFault(guest_ctx, raw_info, raw_context); } @@ -403,81 +377,4 @@ void ArmNce::InvalidateCacheRange(u64 addr, std::size_t size) { this->ClearInstructionCache(); } -TlbEntry* ArmNce::FindTlbEntry(u64 guest_addr) { - std::lock_guard lock(m_tlb_mutex); - - // Simple linear search - more reliable than complex indexing - for (size_t i = 0; i < TLB_SIZE; i++) { - TlbEntry& entry = m_tlb[i]; - if (entry.valid && - guest_addr >= entry.guest_addr && - guest_addr < (entry.guest_addr + entry.size)) { - - // Simple access tracking - just increment counter - if (entry.access_count < 1000) { // Prevent overflow - entry.access_count++; - } - return &entry; - } - } - return nullptr; -} - -void ArmNce::AddTlbEntry(u64 guest_addr, u64 host_addr, u32 size, bool writable) { - // Validate addresses before proceeding - if (!host_addr) { - LOG_ERROR(Core_ARM, "Invalid host address for guest address {:X}", guest_addr); - return; - } - - std::lock_guard lock(m_tlb_mutex); - - // First try to find an invalid entry - size_t replace_idx = TLB_SIZE; - for (size_t i = 0; i < TLB_SIZE; i++) { - if (!m_tlb[i].valid) { - replace_idx = i; - break; - } - } - - // If no invalid entries, use simple LRU - if (replace_idx == TLB_SIZE) { - u32 lowest_count = UINT32_MAX; - for (size_t i = 0; i < TLB_SIZE; i++) { - if (m_tlb[i].access_count < lowest_count) { - lowest_count = m_tlb[i].access_count; - replace_idx = i; - } - } - } - - // Safety check - if (replace_idx >= TLB_SIZE) { - replace_idx = 0; // Fallback to first entry if something went wrong - } - - // Page align the addresses for consistency - const u64 page_mask = size - 1; - const u64 aligned_guest = guest_addr & ~page_mask; - const u64 aligned_host = host_addr & ~page_mask; - - m_tlb[replace_idx] = { - .guest_addr = aligned_guest, - .host_addr = aligned_host, - .size = size, - .valid = true, - .writable = writable, - .last_access_time = 0, // Not used in simplified implementation - .access_count = 1 - }; -} - -void ArmNce::InvalidateTlb() { - std::lock_guard lock(m_tlb_mutex); - for (auto& entry : m_tlb) { - entry.valid = false; - } -} - } // namespace Core diff --git a/src/core/arm/nce/arm_nce.h b/src/core/arm/nce/arm_nce.h index 13da2c8b4..be9b304c4 100644 --- a/src/core/arm/nce/arm_nce.h +++ b/src/core/arm/nce/arm_nce.h @@ -1,11 +1,9 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include -#include #include "core/arm/arm_interface.h" #include "core/arm/nce/guest_context.h" @@ -18,21 +16,6 @@ namespace Core { class System; -struct TlbEntry { - u64 guest_addr; - u64 host_addr; - u32 size; - bool valid; - bool writable; - u64 last_access_time; // For LRU tracking - u32 access_count; // For access frequency tracking -}; - -// Improved TLB configuration -constexpr size_t TLB_SETS = 64; // Number of sets -constexpr size_t TLB_WAYS = 8; // Ways per set -constexpr size_t TLB_SIZE = TLB_SETS * TLB_WAYS; - class ArmNce final : public ArmInterface { public: ArmNce(System& system, bool uses_wall_clock, std::size_t core_index); @@ -107,24 +90,6 @@ public: // Stack for signal processing. std::unique_ptr m_stack{}; - - // Enhanced TLB implementation - std::array m_tlb{}; - std::mutex m_tlb_mutex; - u64 m_tlb_access_counter{0}; - - // TLB helper functions - TlbEntry* FindTlbEntry(u64 guest_addr); - void AddTlbEntry(u64 guest_addr, u64 host_addr, u32 size, bool writable); - void InvalidateTlb(); - size_t GetTlbSetIndex(u64 guest_addr) const; - size_t FindReplacementEntry(size_t set_start); - void UpdateTlbEntryStats(TlbEntry& entry); - - // Thread context caching - std::mutex m_context_mutex; - Kernel::KThread* m_last_thread{nullptr}; - GuestContext m_cached_ctx{}; }; } // namespace Core diff --git a/src/core/hardware_properties.h b/src/core/hardware_properties.h index 191c28bb4..c0bd7fd80 100644 --- a/src/core/hardware_properties.h +++ b/src/core/hardware_properties.h @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -13,7 +14,7 @@ namespace Core { namespace Hardware { -constexpr u64 BASE_CLOCK_RATE = 1'020'000'000; // Default CPU Frequency = 1020 MHz +constexpr u64 BASE_CLOCK_RATE = 1'785'000'000; // Default CPU Frequency = 1785 MHz constexpr u64 CNTFREQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores