From 9cd9ae902a7c32e5d49840609259ff5a77e3af56 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 15 Apr 2017 16:23:48 +0200 Subject: [PATCH] x86-64 support on Android We can do this now that the x86-64 JIT supports PIE. JITIL is deliberately excluded from the GUI because it doesn't support PIE yet. (JITIL will be used if it's set in the INI, though.) --- Source/Android/app/build.gradle | 2 +- .../dolphinemu/dolphinemu/NativeLibrary.java | 2 ++ .../settings/SettingsFragmentPresenter.java | 25 +++++++++++-- .../app/src/main/res/values/arrays.xml | 26 ++++++++++---- Source/Android/jni/MainAndroid.cpp | 9 +++++ Source/Core/Core/ConfigManager.cpp | 2 +- Source/Core/Core/PowerPC/PowerPC.cpp | 26 ++++++++++++++ Source/Core/Core/PowerPC/PowerPC.h | 6 +++- .../DolphinWX/Config/GeneralConfigPane.cpp | 35 ++++++++++--------- .../Core/DolphinWX/Config/GeneralConfigPane.h | 6 ---- 10 files changed, 106 insertions(+), 33 deletions(-) diff --git a/Source/Android/app/build.gradle b/Source/Android/app/build.gradle index c53a0fa3d4..d7590156e4 100644 --- a/Source/Android/app/build.gradle +++ b/Source/Android/app/build.gradle @@ -65,7 +65,7 @@ android { externalNativeBuild { cmake { arguments "-DANDROID_STL=c++_static", "-DCMAKE_BUILD_TYPE=RelWithDebInfo" // , "-DENABLE_GENERIC=ON" - abiFilters "arm64-v8a" //, "armeabi-v7a", "x86_64", "x86" + abiFilters "arm64-v8a", "x86_64" //, "armeabi-v7a", "x86" } } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java index 464d841277..bb9a75194b 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -323,6 +323,8 @@ public final class NativeLibrary */ public static native String GetUserDirectory(); + public static native int DefaultCPUCore(); + /** * Begins emulation. */ diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java index 1ad529afd8..aa02ad3e5c 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java @@ -1,5 +1,6 @@ package org.dolphinemu.dolphinemu.ui.settings; +import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.model.settings.BooleanSetting; import org.dolphinemu.dolphinemu.model.settings.IntSetting; @@ -179,8 +180,28 @@ public final class SettingsFragmentPresenter mView.passSettingsToActivity(mSettings); } - // TODO Set default value for cpuCore based on arch. - sl.add(new SingleChoiceSetting(SettingsFile.KEY_CPU_CORE, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.cpu_core, 0, R.array.emuCoresEntries, R.array.emuCoresValues, 4, cpuCore)); + // TODO: Having different emuCoresEntries/emuCoresValues for each architecture is annoying. + // The proper solution would be to have one emuCoresEntries and one emuCoresValues + // and exclude the values that aren't present in PowerPC::AvailableCPUCores(). + int defaultCpuCore = NativeLibrary.DefaultCPUCore(); + int emuCoresEntries; + int emuCoresValues; + if (defaultCpuCore == 1) // x86-64 + { + emuCoresEntries = R.array.emuCoresEntriesX86_64; + emuCoresValues = R.array.emuCoresValuesX86_64; + } + else if (defaultCpuCore == 4) // AArch64 + { + emuCoresEntries = R.array.emuCoresEntriesARM64; + emuCoresValues = R.array.emuCoresValuesARM64; + } + else + { + emuCoresEntries = R.array.emuCoresEntriesGeneric; + emuCoresValues = R.array.emuCoresValuesGeneric; + } + sl.add(new SingleChoiceSetting(SettingsFile.KEY_CPU_CORE, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.cpu_core, 0, emuCoresEntries, emuCoresValues, defaultCpuCore, cpuCore)); sl.add(new CheckBoxSetting(SettingsFile.KEY_DUAL_CORE, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.dual_core, R.string.dual_core_descrip, true, dualCore)); sl.add(new CheckBoxSetting(SettingsFile.KEY_OVERCLOCK_ENABLE, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.overclock_enable, R.string.overclock_enable_description, false, overclockEnable)); sl.add(new SliderSetting(SettingsFile.KEY_OVERCLOCK_PERCENT, SettingsFile.SECTION_CORE, SettingsFile.SETTINGS_DOLPHIN, R.string.overclock_title, 0, 400, "%", 100, overclock)); diff --git a/Source/Android/app/src/main/res/values/arrays.xml b/Source/Android/app/src/main/res/values/arrays.xml index 4732f14ccf..42b5409884 100644 --- a/Source/Android/app/src/main/res/values/arrays.xml +++ b/Source/Android/app/src/main/res/values/arrays.xml @@ -4,19 +4,33 @@ - + + Interpreter + Cached Interpreter + JIT Recompiler + + + 0 + 5 + 1 + + Interpreter Cached Interpreter JIT ARM64 Recompiler - - + 0 5 4 - + + + Interpreter + Cached Interpreter + + + 0 + 5 diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 4ca2f9c3f9..ed7493aa7c 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -30,6 +30,7 @@ #include "Core/HW/WiimoteReal/WiimoteReal.h" #include "Core/Host.h" #include "Core/PowerPC/JitInterface.h" +#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/Profiler.h" #include "Core/State.h" @@ -453,6 +454,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserDirec JNIEnv* env, jobject obj, jstring jDirectory); JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetUserDirectory(JNIEnv* env, jobject obj); +JNIEXPORT jint JNICALL +Java_org_dolphinemu_dolphinemu_NativeLibrary_DefaultCPUCore(JNIEnv* env, jobject obj); JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetProfiling(JNIEnv* env, jobject obj, jboolean enable); @@ -689,6 +692,12 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetUserDi return env->NewStringUTF(File::GetUserPath(D_USER_IDX).c_str()); } +JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_DefaultCPUCore(JNIEnv* env, + jobject obj) +{ + return PowerPC::DefaultCPUCore(); +} + JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetProfiling(JNIEnv* env, jobject obj, jboolean enable) diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index ffb309c7f7..5338ee1283 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -809,7 +809,7 @@ void SConfig::LoadDefaults() #endif #endif - iCPUCore = PowerPC::CORE_JIT64; + iCPUCore = PowerPC::DefaultCPUCore(); iTimingVariance = 40; bCPUThread = false; bSyncGPUOnSkipIdleHack = true; diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index 2b950f28a3..c6fdaf813e 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -5,6 +5,7 @@ #include "Core/PowerPC/PowerPC.h" #include +#include #include "Common/Assert.h" #include "Common/ChunkFile.h" @@ -180,6 +181,31 @@ static void InitializeCPUCore(int cpu_core) } } +const std::vector& AvailableCPUCores() +{ + static const std::vector cpu_cores = { + CORE_INTERPRETER, CORE_CACHEDINTERPRETER, +#ifdef _M_X86_64 + CORE_JIT64, CORE_JITIL64, +#elif defined(_M_ARM_64) + CORE_JITARM64, +#endif + }; + + return cpu_cores; +} + +CPUCore DefaultCPUCore() +{ +#ifdef _M_X86_64 + return CORE_JIT64; +#elif defined(_M_ARM_64) + return CORE_JITARM64; +#else + return CORE_CACHEDINTERPRETER; +#endif +} + void Init(int cpu_core) { // NOTE: This function runs on EmuThread, not the CPU Thread. diff --git a/Source/Core/Core/PowerPC/PowerPC.h b/Source/Core/Core/PowerPC/PowerPC.h index d323c7918d..4d56b4f6a8 100644 --- a/Source/Core/Core/PowerPC/PowerPC.h +++ b/Source/Core/Core/PowerPC/PowerPC.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "Common/CommonTypes.h" @@ -20,7 +21,7 @@ class PointerWrap; namespace PowerPC { -enum +enum CPUCore { CORE_INTERPRETER, CORE_JIT64, @@ -135,6 +136,9 @@ extern BreakPoints breakpoints; extern MemChecks memchecks; extern PPCDebugInterface debug_interface; +const std::vector& AvailableCPUCores(); +CPUCore DefaultCPUCore(); + void Init(int cpu_core); void Reset(); void Shutdown(); diff --git a/Source/Core/DolphinWX/Config/GeneralConfigPane.cpp b/Source/Core/DolphinWX/Config/GeneralConfigPane.cpp index 6e8f3ac492..e8c41c0aed 100644 --- a/Source/Core/DolphinWX/Config/GeneralConfigPane.cpp +++ b/Source/Core/DolphinWX/Config/GeneralConfigPane.cpp @@ -4,6 +4,10 @@ #include "DolphinWX/Config/GeneralConfigPane.h" +#include +#include +#include + #include #include #include @@ -14,25 +18,23 @@ #include #include +#include "Common/Common.h" #include "Core/Analytics.h" #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/PowerPC/PowerPC.h" #include "DolphinWX/WxEventUtils.h" +static const std::map CPU_CORE_NAMES = { + {PowerPC::CORE_INTERPRETER, _trans("Interpreter (slowest)")}, + {PowerPC::CORE_CACHEDINTERPRETER, _trans("Cached Interpreter (slower)")}, + {PowerPC::CORE_JIT64, _trans("JIT Recompiler (recommended)")}, + {PowerPC::CORE_JITIL64, _trans("JITIL Recompiler (slow, experimental)")}, + {PowerPC::CORE_JITARM64, _trans("JIT Arm64 (experimental)")}, +}; + GeneralConfigPane::GeneralConfigPane(wxWindow* parent, wxWindowID id) : wxPanel(parent, id) { - m_cpu_cores = { - {PowerPC::CORE_INTERPRETER, _("Interpreter (slowest)")}, - {PowerPC::CORE_CACHEDINTERPRETER, _("Cached Interpreter (slower)")}, -#ifdef _M_X86_64 - {PowerPC::CORE_JIT64, _("JIT Recompiler (recommended)")}, - {PowerPC::CORE_JITIL64, _("JITIL Recompiler (slow, experimental)")}, -#elif defined(_M_ARM_64) - {PowerPC::CORE_JITARM64, _("JIT Arm64 (experimental)")}, -#endif - }; - InitializeGUI(); LoadGUIValues(); BindEvents(); @@ -49,8 +51,8 @@ void GeneralConfigPane::InitializeGUI() m_throttler_array_string.Add(wxString::Format(_("%i%%"), i)); } - for (const CPUCore& cpu_core : m_cpu_cores) - m_cpu_engine_array_string.Add(cpu_core.name); + for (PowerPC::CPUCore cpu_core : PowerPC::AvailableCPUCores()) + m_cpu_engine_array_string.Add(wxGetTranslation(CPU_CORE_NAMES.at(cpu_core))); m_dual_core_checkbox = new wxCheckBox(this, wxID_ANY, _("Enable Dual Core (speedup)")); m_cheats_checkbox = new wxCheckBox(this, wxID_ANY, _("Enable Cheats")); @@ -146,9 +148,10 @@ void GeneralConfigPane::LoadGUIValues() if (selection < m_throttler_array_string.size()) m_throttler_choice->SetSelection(selection); - for (size_t i = 0; i < m_cpu_cores.size(); ++i) + const std::vector& cpu_cores = PowerPC::AvailableCPUCores(); + for (size_t i = 0; i < cpu_cores.size(); ++i) { - if (m_cpu_cores[i].CPUid == startup_params.iCPUCore) + if (cpu_cores[i] == startup_params.iCPUCore) m_cpu_engine_radiobox->SetSelection(i); } } @@ -201,7 +204,7 @@ void GeneralConfigPane::OnThrottlerChoiceChanged(wxCommandEvent& event) void GeneralConfigPane::OnCPUEngineRadioBoxChanged(wxCommandEvent& event) { - SConfig::GetInstance().iCPUCore = m_cpu_cores.at(event.GetSelection()).CPUid; + SConfig::GetInstance().iCPUCore = PowerPC::AvailableCPUCores()[event.GetSelection()]; } void GeneralConfigPane::OnAnalyticsCheckBoxChanged(wxCommandEvent& event) diff --git a/Source/Core/DolphinWX/Config/GeneralConfigPane.h b/Source/Core/DolphinWX/Config/GeneralConfigPane.h index d3dce0b8cf..edaa5a79a0 100644 --- a/Source/Core/DolphinWX/Config/GeneralConfigPane.h +++ b/Source/Core/DolphinWX/Config/GeneralConfigPane.h @@ -19,12 +19,6 @@ public: GeneralConfigPane(wxWindow* parent, wxWindowID id); private: - struct CPUCore - { - int CPUid; - wxString name; - }; - std::vector m_cpu_cores; void InitializeGUI(); void LoadGUIValues(); void BindEvents();