aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBix <bix@bixed.xyz>2025-10-05 05:41:20 +0200
committercrueter <crueter@eden-emu.dev>2025-10-05 05:41:20 +0200
commit191dd892e57abad3c56f939e83514ab16dec64ed (patch)
treec1494c49a2735f11b6bc7d7f0095a5d24df0c561
parent9f385bf627e40e2b7d5b06cd83cab0a4e9f98f99 (diff)
[android] Legacy build flavor (#51)
This adds a "legacy" build flavor, similar to the genshinSpoof flavor. The legacy flavor uses a white icon bg, alongside building with `YUZU_LEGACY=ON`, which applies the previously-made SD865 patches iff that value is truthy. Co-authored-by: Bixthefin <114880614+Bixthefin@users.noreply.github.com> Co-authored-by: Calchan <denis.dupeyron@gmail.com> Co-authored-by: crueter <crueter@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/51 Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Reviewed-by: crueter <crueter@eden-emu.dev> Co-authored-by: Bix <bix@bixed.xyz> Co-committed-by: Bix <bix@bixed.xyz>
-rw-r--r--CMakeLists.txt7
-rw-r--r--src/android/app/build.gradle.kts98
-rw-r--r--src/android/app/src/main/legacy/drawable/ic_icon_bg.pngbin0 -> 39026 bytes
-rw-r--r--src/android/app/src/main/legacy/drawable/ic_icon_bg_orig.pngbin0 -> 448880 bytes
-rw-r--r--src/core/arm/nce/arm_nce.cpp2
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h15
-rw-r--r--src/video_core/buffer_cache/buffer_cache_base.h21
-rw-r--r--src/video_core/host1x/host1x.cpp9
-rw-r--r--src/video_core/host1x/host1x.h7
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h9
-rw-r--r--src/video_core/vulkan_common/vulkan_memory_allocator.cpp2
11 files changed, 135 insertions, 35 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7f192887f7..f436c0a183 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -227,6 +227,8 @@ endif()
# TODO(crueter): CI this?
option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON)
+option(YUZU_LEGACY "Apply patches that improve compatibility with older GPUs (e.g. Snapdragon 865) at the cost of performance" OFF)
+
cmake_dependent_option(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF)
cmake_dependent_option(YUZU_ROOM_STANDALONE "Enable standalone room executable" ON "YUZU_ROOM" OFF)
@@ -324,6 +326,11 @@ if (UNIX)
add_compile_definitions(YUZU_UNIX=1)
endif()
+if (YUZU_LEGACY)
+ message(WARNING "Making legacy build. Performance may suffer.")
+ add_compile_definitions(YUZU_LEGACY)
+endif()
+
if (ARCHITECTURE_arm64 AND (ANDROID OR PLATFORM_LINUX))
set(HAS_NCE 1)
add_compile_definitions(HAS_NCE=1)
diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts
index e8d8141711..c85da039cb 100644
--- a/src/android/app/build.gradle.kts
+++ b/src/android/app/build.gradle.kts
@@ -57,8 +57,8 @@ android {
}
defaultConfig {
- // TODO If this is ever modified, change application_id in strings.xml
applicationId = "dev.eden.eden_emulator"
+
minSdk = 28
targetSdk = 36
versionName = getGitVersion()
@@ -72,8 +72,30 @@ android {
buildConfigField("String", "GIT_HASH", "\"${getGitHash()}\"")
buildConfigField("String", "BRANCH", "\"${getBranch()}\"")
+
+ externalNativeBuild {
+ cmake {
+ arguments.addAll(listOf(
+ "-DENABLE_QT=0", // Don't use QT
+ "-DENABLE_SDL2=0", // Don't use SDL
+ "-DENABLE_WEB_SERVICE=1", // Enable web service
+ "-DENABLE_OPENSSL=ON",
+ "-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work
+ "-DYUZU_USE_CPM=ON",
+ "-DCPMUTIL_FORCE_BUNDLED=ON",
+ "-DYUZU_USE_BUNDLED_FFMPEG=ON",
+ "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
+ "-DBUILD_TESTING=OFF",
+ "-DYUZU_TESTS=OFF",
+ "-DDYNARMIC_TESTS=OFF"
+ ))
+
+ abiFilters("arm64-v8a")
+ }
+ }
}
+
val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE")
signingConfigs {
if (keystoreFile != null) {
@@ -94,7 +116,6 @@ android {
// Define build types, which are orthogonal to product flavors.
buildTypes {
-
// Signed by release key, allowing for upload to Play Store.
release {
signingConfig = if (keystoreFile != null) {
@@ -103,7 +124,6 @@ android {
signingConfigs.getByName("default")
}
- resValue("string", "app_name_suffixed", "Eden")
isMinifyEnabled = true
isDebuggable = false
proguardFiles(
@@ -116,7 +136,6 @@ android {
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
register("relWithDebInfo") {
isDefault = true
- resValue("string", "app_name_suffixed", "Eden Debug Release")
signingConfig = signingConfigs.getByName("default")
isDebuggable = true
proguardFiles(
@@ -132,7 +151,6 @@ android {
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
debug {
signingConfig = signingConfigs.getByName("default")
- resValue("string", "app_name_suffixed", "Eden Debug")
isDebuggable = true
isJniDebuggable = true
versionNameSuffix = "-debug"
@@ -140,19 +158,62 @@ android {
}
}
+ // this is really annoying but idk any other ways to fix this behavior
+ applicationVariants.all {
+ val variant = this
+ when {
+ variant.flavorName == "legacy" && variant.buildType.name == "debug" -> {
+ variant.resValue("string", "app_name_suffixed", "Eden Legacy Debug")
+ }
+ variant.flavorName == "mainline" && variant.buildType.name == "debug" -> {
+ variant.resValue("string", "app_name_suffixed", "Eden Debug")
+ }
+ variant.flavorName == "genshinSpoof" && variant.buildType.name == "debug" -> {
+ variant.resValue("string", "app_name_suffixed", "Eden Optimized Debug")
+ }
+ variant.flavorName == "legacy" && variant.buildType.name == "relWithDebInfo" -> {
+ variant.resValue("string", "app_name_suffixed", "Eden Legacy Debug Release")
+ }
+ variant.flavorName == "mainline" && variant.buildType.name == "relWithDebInfo" -> {
+ variant.resValue("string", "app_name_suffixed", "Eden Debug Release")
+ }
+ variant.flavorName == "genshinSpoof" && variant.buildType.name == "relWithDebInfo" -> {
+ variant.resValue("string", "app_name_suffixed", "Eden Optimized Debug Release")
+ }
+ }
+ }
+
android {
flavorDimensions.add("version")
productFlavors {
create("mainline") {
dimension = "version"
- // No need to set applicationId here
+ resValue("string", "app_name_suffixed", "Eden")
}
create("genshinSpoof") {
dimension = "version"
- resValue("string", "app_name_suffixed", "Eden Optimised")
+ resValue("string", "app_name_suffixed", "Eden Optimized")
applicationId = "com.miHoYo.Yuanshen"
}
+
+ create("legacy") {
+ dimension = "version"
+ resValue("string", "app_name_suffixed", "Eden Legacy")
+ applicationId = "dev.legacy.eden_emulator"
+
+ externalNativeBuild {
+ cmake {
+ arguments.add("-DYUZU_LEGACY=ON")
+ }
+ }
+
+ sourceSets {
+ getByName("legacy") {
+ res.srcDirs("src/main/legacy")
+ }
+ }
+ }
}
}
@@ -162,29 +223,6 @@ android {
path = file("../../../CMakeLists.txt")
}
}
-
- defaultConfig {
- externalNativeBuild {
- cmake {
- arguments(
- "-DENABLE_QT=0", // Don't use QT
- "-DENABLE_SDL2=0", // Don't use SDL
- "-DENABLE_WEB_SERVICE=1", // Enable web service
- "-DENABLE_OPENSSL=ON",
- "-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work
- "-DYUZU_USE_CPM=ON",
- "-DCPMUTIL_FORCE_BUNDLED=ON",
- "-DYUZU_USE_BUNDLED_FFMPEG=ON",
- "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
- "-DBUILD_TESTING=OFF",
- "-DYUZU_TESTS=OFF",
- "-DDYNARMIC_TESTS=OFF"
- )
-
- abiFilters("arm64-v8a")
- }
- }
- }
}
tasks.register<Delete>("ktlintReset", fun Delete.() {
diff --git a/src/android/app/src/main/legacy/drawable/ic_icon_bg.png b/src/android/app/src/main/legacy/drawable/ic_icon_bg.png
new file mode 100644
index 0000000000..3327014f8f
--- /dev/null
+++ b/src/android/app/src/main/legacy/drawable/ic_icon_bg.png
Binary files differ
diff --git a/src/android/app/src/main/legacy/drawable/ic_icon_bg_orig.png b/src/android/app/src/main/legacy/drawable/ic_icon_bg_orig.png
new file mode 100644
index 0000000000..a9fc55a4f5
--- /dev/null
+++ b/src/android/app/src/main/legacy/drawable/ic_icon_bg_orig.png
Binary files differ
diff --git a/src/core/arm/nce/arm_nce.cpp b/src/core/arm/nce/arm_nce.cpp
index 877e8ac3c7..0e0d72fc8a 100644
--- a/src/core/arm/nce/arm_nce.cpp
+++ b/src/core/arm/nce/arm_nce.cpp
@@ -227,7 +227,7 @@ HaltReason ArmNce::RunThread(Kernel::KThread* thread) {
if (auto it = post_handlers.find(m_guest_ctx.pc); it != post_handlers.end()) {
hr = ReturnToRunCodeByTrampoline(thread_params, &m_guest_ctx, it->second);
} else {
- hr = ReturnToRunCodeByExceptionLevelChange(m_thread_id, thread_params);
+ hr = ReturnToRunCodeByExceptionLevelChange(m_thread_id, thread_params); // Android: Use "process handle SIGUSR2 -n true -p true -s false" (and SIGURG) in LLDB when debugging
}
// Critical section for thread cleanup
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 6f6e0c23a8..5223afe937 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -26,7 +26,9 @@ BufferCache<P>::BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, R
void(slot_buffers.insert(runtime, NullBufferParams{}));
gpu_modified_ranges.Clear();
inline_buffer_id = NULL_BUFFER_ID;
-
+#ifdef YUZU_LEGACY
+ immediately_free = (Settings::values.vram_usage_mode.GetValue() == Settings::VramUsageMode::Aggressive);
+#endif
if (!runtime.CanReportMemoryUsage()) {
minimum_memory = DEFAULT_EXPECTED_MEMORY;
critical_memory = DEFAULT_CRITICAL_MEMORY;
@@ -1378,6 +1380,10 @@ void BufferCache<P>::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id,
});
new_buffer.MarkUsage(copies[0].dst_offset, copies[0].size);
runtime.CopyBuffer(new_buffer, overlap, copies, true);
+#ifdef YUZU_LEGACY
+ if (immediately_free)
+ runtime.Finish();
+#endif
DeleteBuffer(overlap_id, true);
}
@@ -1668,7 +1674,12 @@ void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
}
Unregister(buffer_id);
- delayed_destruction_ring.Push(std::move(slot_buffers[buffer_id]));
+
+#ifdef YUZU_LEGACY
+ if (!do_not_mark || !immediately_free)
+#endif
+ delayed_destruction_ring.Push(std::move(slot_buffers[buffer_id]));
+
slot_buffers.erase(buffer_id);
if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) {
diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h
index a45e9b35f1..486d19fb79 100644
--- a/src/video_core/buffer_cache/buffer_cache_base.h
+++ b/src/video_core/buffer_cache/buffer_cache_base.h
@@ -154,7 +154,11 @@ template <class P>
class BufferCache : public VideoCommon::ChannelSetupCaches<BufferCacheChannelInfo> {
// Page size for caching purposes.
// This is unrelated to the CPU page size and it can be changed as it seems optimal.
+#ifdef YUZU_LEGACY
+ static constexpr u32 CACHING_PAGEBITS = 12;
+#else
static constexpr u32 CACHING_PAGEBITS = 16;
+#endif
static constexpr u64 CACHING_PAGESIZE = u64{1} << CACHING_PAGEBITS;
static constexpr bool IS_OPENGL = P::IS_OPENGL;
@@ -168,9 +172,14 @@ class BufferCache : public VideoCommon::ChannelSetupCaches<BufferCacheChannelInf
static constexpr bool SEPARATE_IMAGE_BUFFERS_BINDINGS = P::SEPARATE_IMAGE_BUFFER_BINDINGS;
static constexpr bool USE_MEMORY_MAPS_FOR_UPLOADS = P::USE_MEMORY_MAPS_FOR_UPLOADS;
+#ifdef YUZU_LEGACY
+ static constexpr s64 TARGET_THRESHOLD = 3_GiB;
+#else
+ static constexpr s64 TARGET_THRESHOLD = 4_GiB;
+#endif
+
static constexpr s64 DEFAULT_EXPECTED_MEMORY = 512_MiB;
static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB;
- static constexpr s64 TARGET_THRESHOLD = 4_GiB;
// Debug Flags.
@@ -446,7 +455,12 @@ private:
Tegra::MaxwellDeviceMemoryManager& device_memory;
Common::SlotVector<Buffer> slot_buffers;
- DelayedDestructionRing<Buffer, 8> delayed_destruction_ring;
+#ifdef YUZU_LEGACY
+ static constexpr size_t TICKS_TO_DESTROY = 6;
+#else
+ static constexpr size_t TICKS_TO_DESTROY = 8;
+#endif
+ DelayedDestructionRing<Buffer, TICKS_TO_DESTROY> delayed_destruction_ring;
const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect{};
@@ -478,6 +492,9 @@ private:
u64 minimum_memory = 0;
u64 critical_memory = 0;
BufferId inline_buffer_id;
+#ifdef YUZU_LEGACY
+ bool immediately_free = false;
+#endif
std::array<BufferId, ((1ULL << 34) >> CACHING_PAGEBITS)> page_table;
Common::ScratchBuffer<u8> tmp_buffer;
diff --git a/src/video_core/host1x/host1x.cpp b/src/video_core/host1x/host1x.cpp
index 293bca6d79..cec5104144 100644
--- a/src/video_core/host1x/host1x.cpp
+++ b/src/video_core/host1x/host1x.cpp
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -18,9 +21,15 @@ Host1x::~Host1x() = default;
void Host1x::StartDevice(s32 fd, ChannelType type, u32 syncpt) {
switch (type) {
case ChannelType::NvDec:
+#ifdef YUZU_LEGACY
+ std::call_once(nvdec_first_init, []() {std::this_thread::sleep_for(std::chrono::milliseconds{500});}); // HACK: For Astroneer
+#endif
devices[fd] = std::make_unique<Tegra::Host1x::Nvdec>(*this, fd, syncpt, frame_queue);
break;
case ChannelType::VIC:
+#ifdef YUZU_LEGACY
+ std::call_once(vic_first_init, []() {std::this_thread::sleep_for(std::chrono::milliseconds{500});}); // HACK: For Astroneer
+#endif
devices[fd] = std::make_unique<Tegra::Host1x::Vic>(*this, fd, syncpt, frame_queue);
break;
default:
diff --git a/src/video_core/host1x/host1x.h b/src/video_core/host1x/host1x.h
index 8debac93dd..4eea214ec6 100644
--- a/src/video_core/host1x/host1x.h
+++ b/src/video_core/host1x/host1x.h
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -201,6 +204,10 @@ private:
std::unique_ptr<Common::FlatAllocator<u32, 0, 32>> allocator;
FrameQueue frame_queue;
std::unordered_map<s32, std::unique_ptr<CDmaPusher>> devices;
+#ifdef YUZU_LEGACY
+ std::once_flag nvdec_first_init;
+ std::once_flag vic_first_init;
+#endif
};
} // namespace Tegra::Host1x
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index f7d22afde2..01a9a6a3f1 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -110,7 +110,12 @@ class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelI
static constexpr size_t UNSET_CHANNEL{(std::numeric_limits<size_t>::max)()};
+#ifdef YUZU_LEGACY
+ static constexpr s64 TARGET_THRESHOLD = 3_GiB;
+#else
static constexpr s64 TARGET_THRESHOLD = 4_GiB;
+#endif
+
static constexpr s64 DEFAULT_EXPECTED_MEMORY = 1_GiB + 125_MiB;
static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB + 625_MiB;
static constexpr size_t GC_EMERGENCY_COUNTS = 2;
@@ -479,7 +484,11 @@ private:
};
Common::LeastRecentlyUsedCache<LRUItemParams> lru_cache;
+ #ifdef YUZU_LEGACY
+ static constexpr size_t TICKS_TO_DESTROY = 6;
+ #else
static constexpr size_t TICKS_TO_DESTROY = 8;
+#endif
DelayedDestructionRing<Image, TICKS_TO_DESTROY> sentenced_images;
DelayedDestructionRing<ImageView, TICKS_TO_DESTROY> sentenced_image_view;
DelayedDestructionRing<Framebuffer, TICKS_TO_DESTROY> sentenced_framebuffers;
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
index f0309117bf..4cd3442d97 100644
--- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
@@ -325,4 +325,6 @@ namespace Vulkan {
return MemoryCommit(allocator, a, info);
}
+
+
} // namespace Vulkan