diff --git a/.codespellrc b/.codespellrc
index 3336d31fe..9ff49898b 100644
--- a/.codespellrc
+++ b/.codespellrc
@@ -3,4 +3,4 @@
[codespell]
skip = ./.git,./build,./dist,./Doxyfile,./externals,./LICENSES,./src/android/app/src/main/res
-ignore-words-list = aci,allright,ba,canonicalizations,deques,froms,hda,inout,lod,masia,nam,nax,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,vas,zink
+ignore-words-list = aci,allright,ba,canonicalizations,deques,froms,hda,inout,lod,masia,nam,nax,nd,optin,pullrequests,pullrequest,te,transfered,unstall,uscaled,vas,zink,nce
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 151362124..ef10b209f 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
@@ -10,6 +10,7 @@ enum class IntSetting(
override val category: Settings.Category,
override val androidDefault: Int? = null
) : AbstractIntSetting {
+ CPU_BACKEND("cpu_backend", Settings.Category.Cpu),
CPU_ACCURACY("cpu_accuracy", Settings.Category.Cpu),
REGION_INDEX("region_index", Settings.Category.System),
LANGUAGE_INDEX("language_index", Settings.Category.System),
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 6aba69dbe..1f090424b 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
@@ -77,6 +77,15 @@ abstract class SettingsItem(
"%"
)
)
+ put(
+ SingleChoiceSetting(
+ IntSetting.CPU_BACKEND,
+ R.string.cpu_backend,
+ 0,
+ R.array.cpuBackendNames,
+ R.array.cpuBackendValues
+ )
+ )
put(
SingleChoiceSetting(
IntSetting.CPU_ACCURACY,
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 8b71e32f3..7425728c6 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
@@ -269,6 +269,7 @@ class SettingsFragmentPresenter(
add(BooleanSetting.RENDERER_DEBUG.key)
add(HeaderSetting(R.string.cpu))
+ add(IntSetting.CPU_BACKEND.key)
add(IntSetting.CPU_ACCURACY.key)
add(BooleanSetting.CPU_DEBUG_MODE.key)
add(SettingsItem.FASTMEM_COMBINED)
diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml
index 51bcc49a3..2756e5cc9 100644
--- a/src/android/app/src/main/res/values/arrays.xml
+++ b/src/android/app/src/main/res/values/arrays.xml
@@ -175,6 +175,16 @@
- 2
+
+ - @string/cpu_backend_dynarmic
+ - @string/cpu_backend_nce
+
+
+
+ - 0
+ - 1
+
+
- @string/auto
- @string/cpu_accuracy_accurate
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 471af8795..f07121f6a 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -185,6 +185,7 @@
Limits emulation speed to a specified percentage of normal speed.
Limit speed percent
Specifies the percentage to limit emulation speed. 100% is the normal speed. Values higher or lower will increase or decrease the speed limit.
+ CPU Backend
CPU accuracy
%1$s%2$s
@@ -416,6 +417,10 @@
Force 16:10
Stretch to window
+
+ Dynarmic (Slow)
+ Native code execution (NCE)
+
Accurate
Unsafe
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index 38d7b29f7..8a869e558 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -363,13 +363,13 @@ private:
#ifdef ARCHITECTURE_arm64
-uint64_t GetRandomU64() {
+static uint64_t GetRandomU64() {
uint64_t ret;
ASSERT(getrandom(&ret, sizeof(ret), 0) == 0);
return ret;
}
-void* ChooseVirtualBase(size_t virtual_size) {
+static void* ChooseVirtualBase(size_t virtual_size) {
constexpr uintptr_t Map39BitSize = (1ULL << 39);
constexpr uintptr_t Map36BitSize = (1ULL << 36);
@@ -410,7 +410,7 @@ void* ChooseVirtualBase(size_t virtual_size) {
return MAP_FAILED;
}
#else
-void* ChooseVirtualBase(size_t virtual_size) {
+static void* ChooseVirtualBase(size_t virtual_size) {
return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
}
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 81a036ef0..90e7475d7 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -159,7 +159,13 @@ bool IsFastmemEnabled() {
static bool is_nce_enabled = false;
void SetNceEnabled(bool is_39bit) {
- is_nce_enabled = values.cpu_backend.GetValue() == CpuBackend::Nce && is_39bit;
+ const bool is_nce_selected = values.cpu_backend.GetValue() == CpuBackend::Nce;
+ is_nce_enabled = is_nce_selected && is_39bit;
+ if (is_nce_selected && !is_nce_enabled) {
+ LOG_WARNING(
+ Common,
+ "Program does not utilize 39-bit address space, unable to natively execute code");
+ }
}
bool IsNceEnabled() {
diff --git a/src/common/signal_chain.cpp b/src/common/signal_chain.cpp
index e0c6b9d4e..2e4fecc48 100644
--- a/src/common/signal_chain.cpp
+++ b/src/common/signal_chain.cpp
@@ -18,7 +18,7 @@ T* LookupLibcSymbol(const char* name) {
UNREACHABLE_MSG("Failed to open libc!");
}
#else
- // For other operating environments, we assume the symbol is not overriden.
+ // For other operating environments, we assume the symbol is not overridden.
const char* base = nullptr;
Common::DynamicLibrary provider(base);
#endif
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index e7fc8f438..31c00f0a3 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -129,8 +129,10 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
}
metadata.Print();
- // Enable NCE only for 64-bit programs.
- Settings::SetNceEnabled(metadata.Is64BitProgram());
+ // Enable NCE only for programs with 39-bit address space.
+ const bool is_39bit =
+ metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is39Bit;
+ Settings::SetNceEnabled(is_39bit);
const std::array static_modules = {"rtld", "main", "subsdk0", "subsdk1", "subsdk2",
"subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7",
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 49cf90317..76ff38041 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -199,6 +199,7 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process,
codeset.DataSegment().size += bss_size;
program_image.resize(static_cast(program_image.size()) + bss_size);
+ size_t image_size = program_image.size();
#ifdef ARCHITECTURE_arm64
const auto& code = codeset.CodeSegment();
@@ -208,7 +209,6 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process,
// Create NCE patcher
Core::NCE::Patcher patch{};
- size_t image_size = program_image.size();
if (Settings::IsNceEnabled()) {
// Patch SVCs and MRS calls in the guest code