mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-10 03:18:55 +02:00
Compare commits
11 commits
f2c46eadc1
...
a1b50e9339
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1b50e9339 | ||
|
|
f5e2b1fb13 | ||
|
|
6693b99ae4 | ||
|
|
f8ea09fa0f | ||
|
|
361e6209b2 | ||
|
|
3d1a67af18 | ||
|
|
c7b23f4a1a | ||
|
|
38aa2bc5e1 | ||
|
|
1864160326 | ||
|
|
0a169dec4d | ||
|
|
80bafc8fe8 |
34 changed files with 428 additions and 340 deletions
89
.patch/httplib/0002-fix-zstd.patch
Normal file
89
.patch/httplib/0002-fix-zstd.patch
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
From 509be32bbfa6eb95014860f7c9ea6d45c8ddaa56 Mon Sep 17 00:00:00 2001
|
||||
From: crueter <crueter@eden-emu.dev>
|
||||
Date: Sun, 8 Mar 2026 15:11:12 -0400
|
||||
Subject: [PATCH] [cmake] Simplify zstd find logic, and support pre-existing
|
||||
zstd target
|
||||
|
||||
Some deduplication work on the zstd required/if-available logic. Also
|
||||
adds support for pre-existing `zstd::libzstd` which is useful for
|
||||
projects that bundle their own zstd in a way that doesn't get caught by
|
||||
`CONFIG`
|
||||
|
||||
Signed-off-by: crueter <crueter@eden-emu.dev>
|
||||
---
|
||||
CMakeLists.txt | 46 ++++++++++++++++++++++++++--------------------
|
||||
1 file changed, 26 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 1874e36be0..8d31198006 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -241,28 +241,34 @@ endif()
|
||||
# NOTE:
|
||||
# zstd < 1.5.6 does not provide the CMake imported target `zstd::libzstd`.
|
||||
# Older versions must be consumed via their pkg-config file.
|
||||
-if(HTTPLIB_REQUIRE_ZSTD)
|
||||
- find_package(zstd 1.5.6 CONFIG)
|
||||
- if(NOT zstd_FOUND)
|
||||
- find_package(PkgConfig REQUIRED)
|
||||
- pkg_check_modules(zstd REQUIRED IMPORTED_TARGET libzstd)
|
||||
- add_library(zstd::libzstd ALIAS PkgConfig::zstd)
|
||||
- endif()
|
||||
- set(HTTPLIB_IS_USING_ZSTD TRUE)
|
||||
-elseif(HTTPLIB_USE_ZSTD_IF_AVAILABLE)
|
||||
- find_package(zstd 1.5.6 CONFIG QUIET)
|
||||
- if(NOT zstd_FOUND)
|
||||
- find_package(PkgConfig QUIET)
|
||||
- if(PKG_CONFIG_FOUND)
|
||||
- pkg_check_modules(zstd QUIET IMPORTED_TARGET libzstd)
|
||||
-
|
||||
- if(TARGET PkgConfig::zstd)
|
||||
+if (HTTPLIB_REQUIRE_ZSTD)
|
||||
+ set(HTTPLIB_ZSTD_REQUESTED ON)
|
||||
+ set(HTTPLIB_ZSTD_REQUIRED REQUIRED)
|
||||
+elseif (HTTPLIB_USE_ZSTD_IF_AVAILABLE)
|
||||
+ set(HTTPLIB_ZSTD_REQUESTED ON)
|
||||
+ set(HTTPLIB_ZSTD_REQUIRED QUIET)
|
||||
+endif()
|
||||
+
|
||||
+if (HTTPLIB_ZSTD_REQUESTED)
|
||||
+ if (TARGET zstd::libzstd)
|
||||
+ set(HTTPLIB_IS_USING_ZSTD TRUE)
|
||||
+ else()
|
||||
+ find_package(zstd 1.5.6 CONFIG QUIET)
|
||||
+
|
||||
+ if (NOT zstd_FOUND)
|
||||
+ find_package(PkgConfig ${HTTPLIB_ZSTD_REQUIRED})
|
||||
+ pkg_check_modules(zstd ${HTTPLIB_ZSTD_REQUIRED} IMPORTED_TARGET libzstd)
|
||||
+
|
||||
+ if (TARGET PkgConfig::zstd)
|
||||
add_library(zstd::libzstd ALIAS PkgConfig::zstd)
|
||||
endif()
|
||||
endif()
|
||||
+
|
||||
+ # This will always be true if zstd is required.
|
||||
+ # If zstd *isn't* found when zstd is set to required,
|
||||
+ # CMake will error out earlier in this block.
|
||||
+ set(HTTPLIB_IS_USING_ZSTD ${zstd_FOUND})
|
||||
endif()
|
||||
- # Both find_package and PkgConf set a XXX_FOUND var
|
||||
- set(HTTPLIB_IS_USING_ZSTD ${zstd_FOUND})
|
||||
endif()
|
||||
|
||||
# Used for default, common dirs that the end-user can change (if needed)
|
||||
@@ -317,13 +323,13 @@ if(HTTPLIB_COMPILE)
|
||||
$<BUILD_INTERFACE:${_httplib_build_includedir}/httplib.h>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/httplib.h>
|
||||
)
|
||||
-
|
||||
+
|
||||
# Add C++20 module support if requested
|
||||
# Include from separate file to prevent parse errors on older CMake versions
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.28")
|
||||
include(cmake/modules.cmake)
|
||||
endif()
|
||||
-
|
||||
+
|
||||
set_target_properties(${PROJECT_NAME}
|
||||
PROPERTIES
|
||||
VERSION ${${PROJECT_NAME}_VERSION}
|
||||
|
|
@ -46,9 +46,9 @@
|
|||
"package": "ZLIB",
|
||||
"repo": "madler/zlib",
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "06eaa3a1eaaeb31f461a2283b03a91ed8eb2406e62cd97ea1c69836324909edeecd93edd03ff0bf593d9dde223e3376149134c5b1fe2e8688c258cadf8cd60ff",
|
||||
"hash": "16fea4df307a68cf0035858abe2fd550250618a97590e202037acd18a666f57afc10f8836cbbd472d54a0e76539d0e558cb26f059d53de52ff90634bbf4f47d4",
|
||||
"version": "1.2",
|
||||
"git_version": "1.3.1.2",
|
||||
"git_version": "1.3.2",
|
||||
"options": [
|
||||
"ZLIB_BUILD_SHARED OFF",
|
||||
"ZLIB_INSTALL OFF"
|
||||
|
|
@ -98,9 +98,9 @@
|
|||
"package": "VVL",
|
||||
"repo": "KhronosGroup/Vulkan-ValidationLayers",
|
||||
"tag": "vulkan-sdk-%VERSION%",
|
||||
"git_version": "1.4.335.0",
|
||||
"git_version": "1.4.341.0",
|
||||
"artifact": "android-binaries-%VERSION%.zip",
|
||||
"hash": "48167c4a17736301bd08f9290f41830443e1f18cce8ad867fc6f289b49e18b40e93c9850b377951af82f51b5b6d7313aa6a884fc5df79f5ce3df82696c1c1244"
|
||||
"hash": "8812ae84cbe49e6a3418ade9c458d3be6d74a3dffd319d4502007b564d580998056e8190414368ec11b27bc83993c7a0dad713c31bcc3d9553b51243efee3753"
|
||||
},
|
||||
"quazip": {
|
||||
"package": "QuaZip-Qt6",
|
||||
|
|
|
|||
25
externals/cpmfile.json
vendored
25
externals/cpmfile.json
vendored
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"sirit": {
|
||||
"repo": "eden-emulator/sirit",
|
||||
"git_version": "1.0.3",
|
||||
"git_version": "1.0.4",
|
||||
"tag": "v%VERSION%",
|
||||
"artifact": "sirit-source-%VERSION%.tar.zst",
|
||||
"hash_suffix": "sha512sum",
|
||||
|
|
@ -28,11 +28,12 @@
|
|||
"httplib": {
|
||||
"repo": "yhirose/cpp-httplib",
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "a229e24cca4afe78e5c0aa2e482f15108ac34101fd8dbd927365f15e8c37dec4de38c5277d635017d692a5b320e1b929f8bfcc076f52b8e4dcdab8fe53bfdf2e",
|
||||
"git_version": "0.30.1",
|
||||
"hash": "5efa8140aadffe105dcf39935b732476e95755f6c7473ada3d0b64df2bc02c557633ae3948a25b45e1cf67e89a3ff6329fb30362e4ac033b9a1d1e453aa2eded",
|
||||
"git_version": "0.37.0",
|
||||
"find_args": "MODULE GLOBAL",
|
||||
"patches": [
|
||||
"0001-mingw.patch"
|
||||
"0001-mingw.patch",
|
||||
"0002-fix-zstd.patch"
|
||||
],
|
||||
"options": [
|
||||
"HTTPLIB_REQUIRE_OPENSSL ON"
|
||||
|
|
@ -55,8 +56,8 @@
|
|||
"package": "xbyak",
|
||||
"repo": "herumi/xbyak",
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "ac333d7bea1d61865bebebb116201a58db431946aa2f11aa042ef5795c390ff30af4d6c90ed3b3d24443a1d430703b08f14fc13b2fa405c155a241456ed78a47",
|
||||
"git_version": "7.33.2"
|
||||
"hash": "b6475276b2faaeb315734ea8f4f8bd87ededcee768961b39679bee547e7f3e98884d8b7851e176d861dab30a80a76e6ea302f8c111483607dde969b4797ea95a",
|
||||
"git_version": "7.35.2"
|
||||
},
|
||||
"oaknut": {
|
||||
"repo": "eden-emulator/oaknut",
|
||||
|
|
@ -146,9 +147,9 @@
|
|||
"package": "Catch2",
|
||||
"repo": "catchorg/Catch2",
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "acb3f463a7404d6a3bce52e474075cdadf9bb241d93feaf147c182d756e5a2f8bd412f4658ca186d15ab8fed36fc587d79ec311f55642d8e4ded16df9e213656",
|
||||
"hash": "7eea385d79d88a5690cde131fe7ccda97d5c54ea09d6f515000d7bf07c828809d61c1ac99912c1ee507cf933f61c1c47ecdcc45df7850ffa82714034b0fccf35",
|
||||
"version": "3.0.1",
|
||||
"git_version": "3.12.0",
|
||||
"git_version": "3.13.0",
|
||||
"patches": [
|
||||
"0001-solaris-isnan-fix.patch"
|
||||
]
|
||||
|
|
@ -256,15 +257,15 @@
|
|||
"repo": "KhronosGroup/Vulkan-Headers",
|
||||
"package": "VulkanHeaders",
|
||||
"version": "1.4.317",
|
||||
"hash": "26e0ad8fa34ab65a91ca62ddc54cc4410d209a94f64f2817dcdb8061dc621539a4262eab6387e9b9aa421db3dbf2cf8e2a4b041b696d0d03746bae1f25191272",
|
||||
"git_version": "1.4.342",
|
||||
"hash": "d2846ea228415772645eea4b52a9efd33e6a563043dd3de059e798be6391a8f0ca089f455ae420ff22574939ed0f48ed7c6ff3d5a9987d5231dbf3b3f89b484b",
|
||||
"git_version": "1.4.345",
|
||||
"tag": "v%VERSION%"
|
||||
},
|
||||
"vulkan-utility-libraries": {
|
||||
"repo": "KhronosGroup/Vulkan-Utility-Libraries",
|
||||
"package": "VulkanUtilityLibraries",
|
||||
"hash": "8147370f964fd82c315d6bb89adeda30186098427bf3efaa641d36282d42a263f31e96e4586bfd7ae0410ff015379c19aa4512ba160630444d3d8553afd1ec14",
|
||||
"git_version": "1.4.342",
|
||||
"hash": "114f6b237a6dcba923ccc576befb5dea3f1c9b3a30de7dc741f234a831d1c2d52d8a224afb37dd57dffca67ac0df461eaaab6a5ab5e503b393f91c166680c3e1",
|
||||
"git_version": "1.4.345",
|
||||
"tag": "v%VERSION%"
|
||||
},
|
||||
"frozen": {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
|
|||
|
|
@ -40,11 +40,21 @@ class AddonAdapter(val addonViewModel: AddonViewModel) :
|
|||
}
|
||||
}
|
||||
|
||||
val canDelete = model.isRemovable
|
||||
binding.deleteCard.isEnabled = canDelete
|
||||
binding.buttonDelete.isEnabled = canDelete
|
||||
binding.deleteCard.alpha = if (canDelete) 1f else 0.38f
|
||||
|
||||
if (canDelete) {
|
||||
val deleteAction = {
|
||||
addonViewModel.setAddonToDelete(model)
|
||||
}
|
||||
binding.deleteCard.setOnClickListener { deleteAction() }
|
||||
binding.buttonDelete.setOnClickListener { deleteAction() }
|
||||
} else {
|
||||
binding.deleteCard.setOnClickListener(null)
|
||||
binding.buttonDelete.setOnClickListener(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,5 +16,17 @@ data class Patch(
|
|||
val type: Int,
|
||||
val programId: String,
|
||||
val titleId: String,
|
||||
val numericVersion: Long = 0
|
||||
)
|
||||
val numericVersion: Long = 0,
|
||||
val source: Int = 0
|
||||
) {
|
||||
companion object {
|
||||
const val SOURCE_UNKNOWN = 0
|
||||
const val SOURCE_NAND = 1
|
||||
const val SOURCE_SDMC = 2
|
||||
const val SOURCE_EXTERNAL = 3
|
||||
const val SOURCE_PACKED = 4
|
||||
}
|
||||
|
||||
val isRemovable: Boolean
|
||||
get() = source != SOURCE_EXTERNAL && source != SOURCE_PACKED
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1407,7 +1407,7 @@ jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env
|
|||
Common::Android::ToJString(env, patch.version), static_cast<jint>(patch.type),
|
||||
Common::Android::ToJString(env, std::to_string(patch.program_id)),
|
||||
Common::Android::ToJString(env, std::to_string(patch.title_id)),
|
||||
static_cast<jlong>(patch.numeric_version));
|
||||
static_cast<jlong>(patch.numeric_version), static_cast<jint>(patch.source));
|
||||
env->SetObjectArrayElement(jpatchArray, i, jpatch);
|
||||
++i;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -516,7 +516,7 @@ namespace Common::Android {
|
|||
s_patch_class = reinterpret_cast<jclass>(env->NewGlobalRef(patch_class));
|
||||
s_patch_constructor = env->GetMethodID(
|
||||
patch_class, "<init>",
|
||||
"(ZLjava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;J)V");
|
||||
"(ZLjava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;JI)V");
|
||||
s_patch_enabled_field = env->GetFieldID(patch_class, "enabled", "Z");
|
||||
s_patch_name_field = env->GetFieldID(patch_class, "name", "Ljava/lang/String;");
|
||||
s_patch_version_field = env->GetFieldID(patch_class, "version", "Ljava/lang/String;");
|
||||
|
|
|
|||
|
|
@ -777,6 +777,7 @@ struct Values {
|
|||
Setting<bool> reporting_services{
|
||||
linkage, false, "reporting_services", Category::Debugging, Specialization::Default, false};
|
||||
Setting<bool> quest_flag{linkage, false, "quest_flag", Category::Debugging};
|
||||
Setting<bool> use_dev_keys{linkage, false, "use_dev_keys", Category::Debugging};
|
||||
Setting<bool> disable_macro_jit{linkage, false, "disable_macro_jit",
|
||||
Category::DebuggingGraphics};
|
||||
Setting<bool> disable_macro_hle{linkage, false, "disable_macro_hle",
|
||||
|
|
|
|||
|
|
@ -1220,7 +1220,7 @@ target_link_libraries(core PRIVATE
|
|||
RenderDoc::API
|
||||
ZLIB::ZLIB)
|
||||
|
||||
target_link_libraries(core PRIVATE httplib::httplib)
|
||||
target_link_libraries(core PUBLIC httplib::httplib zstd::zstd)
|
||||
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
target_compile_definitions(core PUBLIC ENABLE_WEB_SERVICE)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "common/fs/path_util.h"
|
||||
#include "common/hex_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/crypto/aes_util.h"
|
||||
#include "core/crypto/key_manager.h"
|
||||
|
|
@ -642,8 +643,15 @@ void KeyManager::ReloadKeys() {
|
|||
const auto keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
|
||||
if (!Common::FS::CreateDir(keys_dir))
|
||||
LOG_ERROR(Core, "Failed to create the keys directory.");
|
||||
if (Settings::values.use_dev_keys.GetValue()) {
|
||||
dev_mode = true;
|
||||
LoadFromFile(keys_dir / "dev.keys_autogenerated", false);
|
||||
LoadFromFile(keys_dir / "dev.keys", false);
|
||||
} else {
|
||||
dev_mode = false;
|
||||
LoadFromFile(keys_dir / "prod.keys_autogenerated", false);
|
||||
LoadFromFile(keys_dir / "prod.keys", false);
|
||||
}
|
||||
LoadFromFile(keys_dir / "title.keys_autogenerated", true);
|
||||
LoadFromFile(keys_dir / "title.keys", true);
|
||||
LoadFromFile(keys_dir / "console.keys_autogenerated", false);
|
||||
|
|
@ -838,7 +846,7 @@ void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname,
|
|||
|
||||
std::string filename = "title.keys_autogenerated";
|
||||
if (category == KeyCategory::Standard) {
|
||||
filename = "prod.keys_autogenerated";
|
||||
filename = dev_mode ? "dev.keys_autogenerated" : "prod.keys_autogenerated";
|
||||
} else if (category == KeyCategory::Console) {
|
||||
filename = "console.keys_autogenerated";
|
||||
}
|
||||
|
|
@ -936,6 +944,8 @@ bool KeyManager::KeyFileExists(bool title) {
|
|||
const auto keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
|
||||
if (title)
|
||||
return Common::FS::Exists(keys_dir / "title.keys");
|
||||
if (Settings::values.use_dev_keys.GetValue())
|
||||
return Common::FS::Exists(keys_dir / "dev.keys");
|
||||
return Common::FS::Exists(keys_dir / "prod.keys");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
|
|
@ -314,6 +314,7 @@ private:
|
|||
std::array<u8, 576> eticket_extended_kek{};
|
||||
RSAKeyPair<2048> eticket_rsa_keypair{};
|
||||
|
||||
bool dev_mode;
|
||||
void LoadFromFile(const std::filesystem::path& file_path, bool is_title_keys);
|
||||
|
||||
template <size_t Size>
|
||||
|
|
|
|||
|
|
@ -76,16 +76,16 @@ public:
|
|||
|
||||
template <typename Func>
|
||||
void ApplyOpOnPAddr(PAddr address, Common::ScratchBuffer<u32>& buffer, Func&& operation) {
|
||||
DAddr subbits = static_cast<DAddr>(address & page_mask);
|
||||
DAddr subbits = DAddr(address & page_mask);
|
||||
const u32 base = compressed_device_addr[(address >> page_bits)];
|
||||
if ((base >> MULTI_FLAG_BITS) == 0) [[likely]] {
|
||||
const DAddr d_address = (static_cast<DAddr>(base) << page_bits) + subbits;
|
||||
const DAddr d_address = (DAddr(base) << page_bits) + subbits;
|
||||
operation(d_address);
|
||||
return;
|
||||
}
|
||||
InnerGatherDeviceAddresses(buffer, address);
|
||||
for (u32 value : buffer) {
|
||||
operation((static_cast<DAddr>(value) << page_bits) + subbits);
|
||||
operation((DAddr(value) << page_bits) + subbits);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,12 +96,12 @@ public:
|
|||
}
|
||||
|
||||
PAddr GetPhysicalRawAddressFromDAddr(DAddr address) const {
|
||||
PAddr subbits = static_cast<PAddr>(address & page_mask);
|
||||
auto paddr = compressed_physical_ptr[(address >> page_bits)];
|
||||
PAddr subbits = PAddr(address & page_mask);
|
||||
auto paddr = tracked_entries[(address >> page_bits)].compressed_physical_ptr;
|
||||
if (paddr == 0) {
|
||||
return 0;
|
||||
}
|
||||
return (static_cast<PAddr>(paddr - 1) << page_bits) + subbits;
|
||||
return (PAddr(paddr - 1) << page_bits) + subbits;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -172,9 +172,14 @@ private:
|
|||
|
||||
const uintptr_t physical_base;
|
||||
DeviceInterface* device_inter;
|
||||
Common::VirtualBuffer<u32> compressed_physical_ptr;
|
||||
|
||||
struct TrackedEntry {
|
||||
VAddr cpu_backing_address;
|
||||
u32 continuity_tracker;
|
||||
u32 compressed_physical_ptr;
|
||||
};
|
||||
Common::VirtualBuffer<u32> compressed_device_addr;
|
||||
Common::VirtualBuffer<u32> continuity_tracker;
|
||||
Common::VirtualBuffer<TrackedEntry> tracked_entries;
|
||||
|
||||
// Process memory interfaces
|
||||
|
||||
|
|
@ -189,17 +194,16 @@ private:
|
|||
static constexpr size_t asid_start_bit = guest_max_as_bits;
|
||||
|
||||
std::pair<Asid, VAddr> ExtractCPUBacking(size_t page_index) {
|
||||
auto content = cpu_backing_address[page_index];
|
||||
auto content = tracked_entries[page_index].cpu_backing_address;
|
||||
const VAddr address = content & guest_mask;
|
||||
const Asid asid{static_cast<size_t>(content >> asid_start_bit)};
|
||||
return std::make_pair(asid, address);
|
||||
}
|
||||
|
||||
void InsertCPUBacking(size_t page_index, VAddr address, Asid asid) {
|
||||
cpu_backing_address[page_index] = address | (asid.id << asid_start_bit);
|
||||
tracked_entries[page_index].cpu_backing_address = address | (asid.id << asid_start_bit);
|
||||
}
|
||||
|
||||
Common::VirtualBuffer<VAddr> cpu_backing_address;
|
||||
std::array<TranslationEntry, 4> t_slot{};
|
||||
u32 cache_cursor = 0;
|
||||
using CounterType = u8;
|
||||
|
|
|
|||
|
|
@ -166,29 +166,21 @@ struct DeviceMemoryManagerAllocator {
|
|||
|
||||
template <typename Traits>
|
||||
DeviceMemoryManager<Traits>::DeviceMemoryManager(const DeviceMemory& device_memory_)
|
||||
: physical_base{reinterpret_cast<const uintptr_t>(device_memory_.buffer.BackingBasePointer())},
|
||||
device_inter{nullptr}, compressed_physical_ptr(device_as_size >> Memory::YUZU_PAGEBITS),
|
||||
compressed_device_addr(1ULL << ((Settings::values.memory_layout_mode.GetValue() ==
|
||||
Settings::MemoryLayout::Memory_4Gb
|
||||
? physical_min_bits
|
||||
: physical_max_bits) -
|
||||
Memory::YUZU_PAGEBITS)),
|
||||
continuity_tracker(device_as_size >> Memory::YUZU_PAGEBITS),
|
||||
cpu_backing_address(device_as_size >> Memory::YUZU_PAGEBITS) {
|
||||
: physical_base{uintptr_t(device_memory_.buffer.BackingBasePointer())}
|
||||
, device_inter{nullptr}
|
||||
, compressed_device_addr(1ULL << ((Settings::values.memory_layout_mode.GetValue() == Settings::MemoryLayout::Memory_4Gb ? physical_min_bits : physical_max_bits) - Memory::YUZU_PAGEBITS))
|
||||
, tracked_entries(device_as_size >> Memory::YUZU_PAGEBITS)
|
||||
{
|
||||
impl = std::make_unique<DeviceMemoryManagerAllocator<Traits>>();
|
||||
cached_pages = std::make_unique<CachedPages>();
|
||||
|
||||
const size_t total_virtual = device_as_size >> Memory::YUZU_PAGEBITS;
|
||||
for (size_t i = 0; i < total_virtual; i++) {
|
||||
compressed_physical_ptr[i] = 0;
|
||||
continuity_tracker[i] = 1;
|
||||
cpu_backing_address[i] = 0;
|
||||
tracked_entries[i].compressed_physical_ptr = 0;
|
||||
tracked_entries[i].continuity_tracker = 1;
|
||||
tracked_entries[i].cpu_backing_address = 0;
|
||||
}
|
||||
const size_t total_phys = 1ULL << ((Settings::values.memory_layout_mode.GetValue() ==
|
||||
Settings::MemoryLayout::Memory_4Gb
|
||||
? physical_min_bits
|
||||
: physical_max_bits) -
|
||||
Memory::YUZU_PAGEBITS);
|
||||
const size_t total_phys = 1ULL << ((Settings::values.memory_layout_mode.GetValue() == Settings::MemoryLayout::Memory_4Gb ? physical_min_bits : physical_max_bits) - Memory::YUZU_PAGEBITS);
|
||||
for (size_t i = 0; i < total_phys; i++) {
|
||||
compressed_device_addr[i] = 0;
|
||||
}
|
||||
|
|
@ -228,11 +220,11 @@ void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size
|
|||
const VAddr new_vaddress = virtual_address + i * Memory::YUZU_PAGESIZE;
|
||||
auto* ptr = process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress));
|
||||
if (ptr == nullptr) [[unlikely]] {
|
||||
compressed_physical_ptr[start_page_d + i] = 0;
|
||||
tracked_entries[start_page_d + i].compressed_physical_ptr = 0;
|
||||
continue;
|
||||
}
|
||||
auto phys_addr = static_cast<u32>(GetRawPhysicalAddr(ptr) >> Memory::YUZU_PAGEBITS) + 1U;
|
||||
compressed_physical_ptr[start_page_d + i] = phys_addr;
|
||||
tracked_entries[start_page_d + i].compressed_physical_ptr = phys_addr;
|
||||
InsertCPUBacking(start_page_d + i, new_vaddress, asid);
|
||||
const u32 base_dev = compressed_device_addr[phys_addr - 1U];
|
||||
const u32 new_dev = static_cast<u32>(start_page_d + i);
|
||||
|
|
@ -260,9 +252,9 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) {
|
|||
device_inter->InvalidateRegion(address, size);
|
||||
std::scoped_lock lk(mapping_guard);
|
||||
for (size_t i = 0; i < num_pages; i++) {
|
||||
auto phys_addr = compressed_physical_ptr[start_page_d + i];
|
||||
compressed_physical_ptr[start_page_d + i] = 0;
|
||||
cpu_backing_address[start_page_d + i] = 0;
|
||||
auto phys_addr = tracked_entries[start_page_d + i].compressed_physical_ptr;
|
||||
tracked_entries[start_page_d + i].compressed_physical_ptr = 0;
|
||||
tracked_entries[start_page_d + i].cpu_backing_address = 0;
|
||||
if (phys_addr != 0) [[likely]] {
|
||||
const u32 base_dev = compressed_device_addr[phys_addr - 1U];
|
||||
if ((base_dev >> MULTI_FLAG_BITS) == 0) [[likely]] {
|
||||
|
|
@ -300,14 +292,14 @@ void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtu
|
|||
page_count = 1;
|
||||
}
|
||||
last_ptr = new_ptr;
|
||||
continuity_tracker[start_page_d + index] = static_cast<u32>(page_count);
|
||||
tracked_entries[start_page_d + index].continuity_tracker = static_cast<u32>(page_count);
|
||||
}
|
||||
}
|
||||
template <typename Traits>
|
||||
u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) {
|
||||
size_t page_index = src_addr >> page_bits;
|
||||
size_t subbits = src_addr & page_mask;
|
||||
if ((static_cast<size_t>(continuity_tracker[page_index]) << page_bits) >= size + subbits) {
|
||||
if ((static_cast<size_t>(tracked_entries[page_index].continuity_tracker) << page_bits) >= size + subbits) {
|
||||
return GetPointer<u8>(src_addr);
|
||||
}
|
||||
return nullptr;
|
||||
|
|
@ -317,7 +309,7 @@ template <typename Traits>
|
|||
const u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) const {
|
||||
size_t page_index = src_addr >> page_bits;
|
||||
size_t subbits = src_addr & page_mask;
|
||||
if ((static_cast<size_t>(continuity_tracker[page_index]) << page_bits) >= size + subbits) {
|
||||
if ((static_cast<size_t>(tracked_entries[page_index].continuity_tracker) << page_bits) >= size + subbits) {
|
||||
return GetPointer<u8>(src_addr);
|
||||
}
|
||||
return nullptr;
|
||||
|
|
@ -342,12 +334,10 @@ template <typename T>
|
|||
T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) {
|
||||
const size_t index = address >> Memory::YUZU_PAGEBITS;
|
||||
const size_t offset = address & Memory::YUZU_PAGEMASK;
|
||||
auto phys_addr = compressed_physical_ptr[index];
|
||||
if (phys_addr == 0) [[unlikely]] {
|
||||
auto phys_addr = tracked_entries[index].compressed_physical_ptr;
|
||||
if (phys_addr == 0) [[unlikely]]
|
||||
return nullptr;
|
||||
}
|
||||
return GetPointerFromRaw<T>((static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) +
|
||||
offset);
|
||||
return GetPointerFromRaw<T>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS) + offset);
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
|
|
@ -355,12 +345,10 @@ template <typename T>
|
|||
const T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) const {
|
||||
const size_t index = address >> Memory::YUZU_PAGEBITS;
|
||||
const size_t offset = address & Memory::YUZU_PAGEMASK;
|
||||
auto phys_addr = compressed_physical_ptr[index];
|
||||
if (phys_addr == 0) [[unlikely]] {
|
||||
auto phys_addr = tracked_entries[index].compressed_physical_ptr;
|
||||
if (phys_addr == 0)
|
||||
return nullptr;
|
||||
}
|
||||
return GetPointerFromRaw<T>((static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) +
|
||||
offset);
|
||||
return GetPointerFromRaw<T>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS) + offset);
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
|
|
@ -386,18 +374,14 @@ T DeviceMemoryManager<Traits>::Read(DAddr address) const {
|
|||
}
|
||||
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto on_unmapped,
|
||||
auto on_memory, auto increment) {
|
||||
void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto on_unmapped, auto on_memory, auto increment) {
|
||||
std::size_t remaining_size = size;
|
||||
std::size_t page_index = addr >> Memory::YUZU_PAGEBITS;
|
||||
std::size_t page_offset = addr & Memory::YUZU_PAGEMASK;
|
||||
|
||||
while (remaining_size) {
|
||||
const size_t next_pages = static_cast<std::size_t>(continuity_tracker[page_index]);
|
||||
const std::size_t copy_amount =
|
||||
(std::min)((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);
|
||||
const auto current_vaddr =
|
||||
static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset);
|
||||
const size_t next_pages = std::size_t(tracked_entries[page_index].continuity_tracker);
|
||||
const std::size_t copy_amount = (std::min)((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);
|
||||
const auto current_vaddr = u64((page_index << Memory::YUZU_PAGEBITS) + page_offset);
|
||||
SCOPE_EXIT{
|
||||
page_index += next_pages;
|
||||
page_offset = 0;
|
||||
|
|
@ -405,13 +389,12 @@ void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto o
|
|||
remaining_size -= copy_amount;
|
||||
};
|
||||
|
||||
auto phys_addr = compressed_physical_ptr[page_index];
|
||||
auto phys_addr = tracked_entries[page_index].compressed_physical_ptr;
|
||||
if (phys_addr == 0) {
|
||||
on_unmapped(copy_amount, current_vaddr);
|
||||
continue;
|
||||
}
|
||||
auto* mem_ptr = GetPointerFromRaw<u8>(
|
||||
(static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) + page_offset);
|
||||
auto* mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS) + page_offset);
|
||||
on_memory(copy_amount, mem_ptr);
|
||||
}
|
||||
}
|
||||
|
|
@ -430,7 +413,7 @@ void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, s
|
|||
}
|
||||
|
||||
const std::size_t page_index = address >> Memory::YUZU_PAGEBITS;
|
||||
const auto phys_addr = compressed_physical_ptr[page_index];
|
||||
const auto phys_addr = tracked_entries[page_index].compressed_physical_ptr;
|
||||
if (phys_addr != 0) {
|
||||
auto* const mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS));
|
||||
t_slot[cache_cursor % t_slot.size()] = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
|
||||
|
|
@ -488,7 +471,7 @@ void DeviceMemoryManager<Traits>::ReadBlockUnsafe(DAddr address, void* dest_poin
|
|||
}
|
||||
|
||||
const std::size_t page_index = address >> Memory::YUZU_PAGEBITS;
|
||||
const auto phys_addr = compressed_physical_ptr[page_index];
|
||||
const auto phys_addr = tracked_entries[page_index].compressed_physical_ptr;
|
||||
if (phys_addr != 0) {
|
||||
auto* const mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS));
|
||||
t_slot[cache_cursor % t_slot.size()] = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
|
||||
|
|
|
|||
|
|
@ -123,6 +123,39 @@ bool IsVersionedExternalUpdateDisabled(const std::vector<std::string>& disabled,
|
|||
return std::find(disabled.cbegin(), disabled.cend(), disabled_key) != disabled.cend() ||
|
||||
std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend();
|
||||
}
|
||||
|
||||
std::string GetUpdateVersionStringFromSlot(const ContentProvider* provider, u64 update_tid) {
|
||||
if (provider == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto control_nca = provider->GetEntry(update_tid, ContentRecordType::Control);
|
||||
if (control_nca == nullptr ||
|
||||
control_nca->GetStatus() != Loader::ResultStatus::Success) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto romfs = control_nca->GetRomFS();
|
||||
if (romfs == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto extracted = ExtractRomFS(romfs);
|
||||
if (extracted == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto nacp_file = extracted->GetFile("control.nacp");
|
||||
if (nacp_file == nullptr) {
|
||||
nacp_file = extracted->GetFile("Control.nacp");
|
||||
}
|
||||
if (nacp_file == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
NACP nacp{nacp_file};
|
||||
return nacp.GetVersionString();
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
PatchManager::PatchManager(u64 title_id_,
|
||||
|
|
@ -771,6 +804,7 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||
std::nullopt, std::nullopt, ContentRecordType::Program, update_tid);
|
||||
|
||||
for (const auto& [slot, entry] : all_updates) {
|
||||
(void)entry;
|
||||
if (slot == ContentProviderUnionSlot::External ||
|
||||
slot == ContentProviderUnionSlot::FrontendManual) {
|
||||
continue;
|
||||
|
|
@ -786,7 +820,7 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||
source_suffix = " (NAND)";
|
||||
break;
|
||||
case ContentProviderUnionSlot::SDMC:
|
||||
source_type = PatchSource::NAND;
|
||||
source_type = PatchSource::SDMC;
|
||||
source_suffix = " (SDMC)";
|
||||
break;
|
||||
default:
|
||||
|
|
@ -795,21 +829,18 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||
|
||||
std::string version_str;
|
||||
u32 numeric_ver = 0;
|
||||
PatchManager update{update_tid, fs_controller, content_provider};
|
||||
const auto metadata = update.GetControlMetadata();
|
||||
const auto& nacp = metadata.first;
|
||||
const auto* slot_provider = content_union->GetSlotProvider(slot);
|
||||
version_str = GetUpdateVersionStringFromSlot(slot_provider, update_tid);
|
||||
|
||||
if (nacp != nullptr) {
|
||||
version_str = nacp->GetVersionString();
|
||||
}
|
||||
|
||||
const auto meta_ver = content_provider.GetEntryVersion(update_tid);
|
||||
if (meta_ver.has_value()) {
|
||||
numeric_ver = *meta_ver;
|
||||
if (slot_provider != nullptr) {
|
||||
const auto slot_ver = slot_provider->GetEntryVersion(update_tid);
|
||||
if (slot_ver.has_value()) {
|
||||
numeric_ver = *slot_ver;
|
||||
if (version_str.empty() && numeric_ver != 0) {
|
||||
version_str = FormatTitleVersion(numeric_ver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string patch_name = "Update" + source_suffix;
|
||||
|
||||
|
|
@ -956,37 +987,60 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||
}
|
||||
|
||||
// DLC
|
||||
const auto dlc_entries =
|
||||
content_provider.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data);
|
||||
|
||||
std::vector<ContentProviderEntry> dlc_match;
|
||||
dlc_match.reserve(dlc_entries.size());
|
||||
std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match),
|
||||
[this](const ContentProviderEntry& entry) {
|
||||
bool has_external_dlc = false;
|
||||
bool has_nand_dlc = false;
|
||||
bool has_sdmc_dlc = false;
|
||||
bool has_other_dlc = false;
|
||||
const auto dlc_entries_with_origin =
|
||||
content_union->ListEntriesFilterOrigin(std::nullopt, TitleType::AOC, ContentRecordType::Data);
|
||||
|
||||
dlc_match.reserve(dlc_entries_with_origin.size());
|
||||
for (const auto& [slot, entry] : dlc_entries_with_origin) {
|
||||
const auto base_tid = GetBaseTitleID(entry.title_id);
|
||||
const bool matches_base = base_tid == title_id;
|
||||
|
||||
if (!matches_base) {
|
||||
LOG_DEBUG(Loader, "DLC {:016X} base {:016X} doesn't match title {:016X}",
|
||||
entry.title_id, base_tid, title_id);
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto nca = content_provider.GetEntry(entry);
|
||||
const auto* slot_provider = content_union->GetSlotProvider(slot);
|
||||
if (slot_provider == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto nca = slot_provider->GetEntry(entry);
|
||||
if (!nca) {
|
||||
LOG_DEBUG(Loader, "Failed to get NCA for DLC {:016X}", entry.title_id);
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto status = nca->GetStatus();
|
||||
if (status != Loader::ResultStatus::Success) {
|
||||
LOG_DEBUG(Loader, "DLC {:016X} NCA has status {}",
|
||||
entry.title_id, static_cast<int>(status));
|
||||
return false;
|
||||
LOG_DEBUG(Loader, "DLC {:016X} NCA has status {}", entry.title_id,
|
||||
static_cast<int>(status));
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
switch (slot) {
|
||||
case ContentProviderUnionSlot::External:
|
||||
case ContentProviderUnionSlot::FrontendManual:
|
||||
has_external_dlc = true;
|
||||
break;
|
||||
case ContentProviderUnionSlot::UserNAND:
|
||||
case ContentProviderUnionSlot::SysNAND:
|
||||
has_nand_dlc = true;
|
||||
break;
|
||||
case ContentProviderUnionSlot::SDMC:
|
||||
has_sdmc_dlc = true;
|
||||
break;
|
||||
default:
|
||||
has_other_dlc = true;
|
||||
break;
|
||||
}
|
||||
dlc_match.push_back(entry);
|
||||
}
|
||||
|
||||
if (!dlc_match.empty()) {
|
||||
// Ensure sorted so DLC IDs show in order.
|
||||
|
|
@ -1000,13 +1054,22 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||
|
||||
const auto dlc_disabled =
|
||||
std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end();
|
||||
PatchSource dlc_source = PatchSource::Unknown;
|
||||
if (has_external_dlc && !has_nand_dlc && !has_sdmc_dlc && !has_other_dlc) {
|
||||
dlc_source = PatchSource::External;
|
||||
} else if (has_nand_dlc && !has_external_dlc && !has_sdmc_dlc && !has_other_dlc) {
|
||||
dlc_source = PatchSource::NAND;
|
||||
} else if (has_sdmc_dlc && !has_external_dlc && !has_nand_dlc && !has_other_dlc) {
|
||||
dlc_source = PatchSource::SDMC;
|
||||
}
|
||||
|
||||
out.push_back({.enabled = !dlc_disabled,
|
||||
.name = "DLC",
|
||||
.version = std::move(list),
|
||||
.type = PatchType::DLC,
|
||||
.program_id = title_id,
|
||||
.title_id = dlc_match.back().title_id,
|
||||
.source = PatchSource::Unknown});
|
||||
.source = dlc_source});
|
||||
}
|
||||
|
||||
return out;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ enum class PatchType { Update, DLC, Mod };
|
|||
enum class PatchSource {
|
||||
Unknown,
|
||||
NAND,
|
||||
SDMC,
|
||||
External,
|
||||
Packed,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -104,7 +107,8 @@ Result TimeZoneService::LoadLocationNameList(
|
|||
OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) {
|
||||
SCOPE_EXIT {
|
||||
LOG_DEBUG(Service_Time, "called. index={} out_count={} out_names[0]={} out_names[1]={}",
|
||||
index, *out_count, out_names[0], out_names[1]);
|
||||
index, *out_count, out_names.size() > 0 ? out_names[0] : Service::PSC::Time::LocationName{},
|
||||
out_names.size() > 1 ? out_names[1] : Service::PSC::Time::LocationName{});
|
||||
};
|
||||
|
||||
std::scoped_lock l{m_mutex};
|
||||
|
|
@ -208,7 +212,8 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
|||
SCOPE_EXIT {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
calendar_time, *out_count, out_times.size() > 0 ? out_times[0] : s64{0},
|
||||
out_times.size() > 1 ? out_times[1] : s64{0});
|
||||
};
|
||||
|
||||
R_RETURN(m_wrapped_service->ToPosixTime(out_count, out_times, calendar_time, rule));
|
||||
|
|
@ -220,7 +225,8 @@ Result TimeZoneService::ToPosixTimeWithMyRule(
|
|||
SCOPE_EXIT {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
calendar_time, *out_count, out_times.size() > 0 ? out_times[0] : s64{0},
|
||||
out_times.size() > 1 ? out_times[1] : s64{0});
|
||||
};
|
||||
|
||||
R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, calendar_time));
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -148,7 +151,8 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
|||
SCOPE_EXIT {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
calendar_time, *out_count, out_times.size() > 0 ? out_times[0] : s64{0},
|
||||
out_times.size() > 1 ? out_times[1] : s64{0});
|
||||
};
|
||||
|
||||
R_RETURN(
|
||||
|
|
@ -161,7 +165,8 @@ Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
|
|||
SCOPE_EXIT {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
calendar_time, *out_count, out_times.size() > 0 ? out_times[0] : s64{0},
|
||||
out_times.size() > 1 ? out_times[1] : s64{0});
|
||||
};
|
||||
|
||||
R_RETURN(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
|
|
@ -29,10 +29,13 @@ namespace Service {
|
|||
return function_string;
|
||||
}
|
||||
|
||||
ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_,
|
||||
u32 max_sessions_, InvokerFn* handler_invoker_)
|
||||
: SessionRequestHandler(system_.Kernel(), service_name_), system{system_},
|
||||
service_name{service_name_}, handler_invoker{handler_invoker_}, max_sessions{max_sessions_} {}
|
||||
ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_, u32 max_sessions_, InvokerFn* handler_invoker_)
|
||||
: SessionRequestHandler(system_.Kernel(), service_name_)
|
||||
, system{system_}
|
||||
, service_name{service_name_}
|
||||
, handler_invoker{handler_invoker_}
|
||||
, max_sessions{max_sessions_}
|
||||
{}
|
||||
|
||||
ServiceFrameworkBase::~ServiceFrameworkBase() {
|
||||
// Wait for other threads to release access before destroying
|
||||
|
|
@ -50,8 +53,7 @@ void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* func
|
|||
// Usually this array is sorted by id already, so hint to insert at the end
|
||||
handlers_tipc.reserve(handlers_tipc.size() + n);
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header,
|
||||
functions[i]);
|
||||
handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header, functions[i]);
|
||||
}
|
||||
|
||||
void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
|
|
@ -8,8 +8,7 @@
|
|||
|
||||
#include <cstddef>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <boost/container/flat_map.hpp>
|
||||
#include <ankerl/unordered_dense.h>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/hle_ipc.h"
|
||||
|
||||
|
|
@ -78,13 +77,6 @@ protected:
|
|||
[[nodiscard]] virtual std::unique_lock<std::mutex> LockService() noexcept {
|
||||
return std::unique_lock{lock_service};
|
||||
}
|
||||
|
||||
/// System context that the service operates under.
|
||||
Core::System& system;
|
||||
|
||||
/// Identifier string used to connect to the service.
|
||||
std::string service_name;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
friend class ServiceFramework;
|
||||
|
|
@ -106,16 +98,19 @@ private:
|
|||
void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n);
|
||||
void ReportUnimplementedFunction(HLERequestContext& ctx, const FunctionInfoBase* info);
|
||||
|
||||
boost::container::flat_map<u32, FunctionInfoBase> handlers;
|
||||
boost::container::flat_map<u32, FunctionInfoBase> handlers_tipc;
|
||||
protected:
|
||||
ankerl::unordered_dense::map<u32, FunctionInfoBase> handlers;
|
||||
ankerl::unordered_dense::map<u32, FunctionInfoBase> handlers_tipc;
|
||||
/// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
|
||||
std::mutex lock_service;
|
||||
/// System context that the service operates under.
|
||||
Core::System& system;
|
||||
/// Identifier string used to connect to the service.
|
||||
const char* service_name;
|
||||
/// Function used to safely up-cast pointers to the derived class before invoking a handler.
|
||||
InvokerFn* handler_invoker;
|
||||
|
||||
/// Maximum number of concurrent sessions that this service can handle.
|
||||
u32 max_sessions;
|
||||
|
||||
/// Flag to store if a port was already create/installed to detect multiple install attempts,
|
||||
/// which is not supported.
|
||||
bool service_registered = false;
|
||||
|
|
@ -159,8 +154,7 @@ protected:
|
|||
* @param max_sessions_ Maximum number of sessions that can be connected to this service at the
|
||||
* same time.
|
||||
*/
|
||||
explicit ServiceFramework(Core::System& system_, const char* service_name_,
|
||||
u32 max_sessions_ = ServerSessionCountMax)
|
||||
explicit ServiceFramework(Core::System& system_, const char* service_name_, u32 max_sessions_ = ServerSessionCountMax)
|
||||
: ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker) {}
|
||||
|
||||
/// Registers handlers in the service.
|
||||
|
|
@ -219,7 +213,7 @@ private:
|
|||
static void Invoker(ServiceFrameworkBase* object, HandlerFnP<ServiceFrameworkBase> member,
|
||||
HLERequestContext& ctx) {
|
||||
// Cast back up to our original types and call the member function
|
||||
(static_cast<Self*>(object)->*static_cast<HandlerFnP<Self>>(member))(ctx);
|
||||
(static_cast<Self*>(object)->*HandlerFnP<Self>(member))(ctx);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
Copyright (C) 2017 merryhime <git@mary.rs>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for
|
||||
any purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
|
@ -687,7 +687,7 @@ void A32EmitX64::EmitA32BXWritePC(A32EmitContext& ctx, IR::Inst* inst) {
|
|||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
auto& arg = args[0];
|
||||
|
||||
const u32 upper_without_t = (ctx.EndLocation().SetSingleStepping(false).UniqueHash() >> 32) & 0xFFFFFFFE;
|
||||
const u64 upper_without_t = (ctx.EndLocation().SetSingleStepping(false).UniqueHash() >> 32) & 0xFFFFFFFE;
|
||||
|
||||
// Pseudocode:
|
||||
// if (new_pc & 1) {
|
||||
|
|
|
|||
|
|
@ -947,7 +947,7 @@ static void EmitAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, size_t
|
|||
const Xbyak::Reg8 overflow = overflow_inst ? ctx.reg_alloc.ScratchGpr(code).cvt8() : Xbyak::Reg8{-1};
|
||||
|
||||
if (args[1].IsImmediate() && args[1].GetType() == IR::Type::U32) {
|
||||
const u32 op_arg = args[1].GetImmediateU32();
|
||||
const u64 op_arg = args[1].GetImmediateU64();
|
||||
if (carry_in.IsImmediate()) {
|
||||
if (carry_in.GetImmediateU1()) {
|
||||
// In range for a valid LEA materialisation
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/* This file is part of the dynarmic project.
|
||||
|
|
@ -135,7 +135,7 @@ void EmitX64::EmitSignedSaturation(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
const u32 mask = (1u << N) - 1;
|
||||
const u32 positive_saturated_value = (1u << (N - 1)) - 1;
|
||||
const u32 negative_saturated_value = 1u << (N - 1);
|
||||
const u64 negative_saturated_value = 1u << (N - 1);
|
||||
|
||||
const Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr(code).cvt32();
|
||||
const Xbyak::Reg32 reg_a = ctx.reg_alloc.UseGpr(code, args[0]).cvt32();
|
||||
|
|
|
|||
|
|
@ -343,8 +343,8 @@ void AddOffsetToCoordinates(EmitContext& ctx, const IR::TextureInstInfo& info, I
|
|||
break;
|
||||
}
|
||||
case TextureType::ColorArray2D:
|
||||
offset = ctx.OpCompositeConstruct(ctx.U32[3], ctx.OpCompositeExtract(ctx.U32[1], coords, 0),
|
||||
ctx.OpCompositeExtract(ctx.U32[1], coords, 1),
|
||||
offset = ctx.OpCompositeConstruct(ctx.U32[3], ctx.OpCompositeExtract(ctx.U32[1], offset, 0),
|
||||
ctx.OpCompositeExtract(ctx.U32[1], offset, 1),
|
||||
ctx.u32_zero_value);
|
||||
[[fallthrough]];
|
||||
case TextureType::Color3D: {
|
||||
|
|
|
|||
|
|
@ -70,14 +70,10 @@ TextureCache<P>::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag
|
|||
(std::max)((std::min)(device_local_memory - min_vacancy_critical, min_spacing_critical),
|
||||
DEFAULT_CRITICAL_MEMORY));
|
||||
minimum_memory = static_cast<u64>((device_local_memory - mem_threshold) / 2);
|
||||
|
||||
lowmemorydevice = false;
|
||||
} else {
|
||||
expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB;
|
||||
critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB;
|
||||
minimum_memory = 0;
|
||||
|
||||
lowmemorydevice = true;
|
||||
}
|
||||
|
||||
const bool gpu_unswizzle_enabled = Settings::values.gpu_unswizzle_enabled.GetValue();
|
||||
|
|
@ -122,102 +118,46 @@ void TextureCache<P>::RunGarbageCollector() {
|
|||
bool aggressive_mode = false;
|
||||
u64 ticks_to_destroy = 0;
|
||||
size_t num_iterations = 0;
|
||||
|
||||
const auto Configure = [&](bool allow_aggressive) {
|
||||
high_priority_mode = total_used_memory >= expected_memory;
|
||||
aggressive_mode = allow_aggressive && total_used_memory >= critical_memory;
|
||||
ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 50ULL;
|
||||
num_iterations = aggressive_mode ? 40 : (high_priority_mode ? 20 : 10);
|
||||
};
|
||||
|
||||
const auto Cleanup = [this, &num_iterations, &high_priority_mode,
|
||||
&aggressive_mode](ImageId image_id) {
|
||||
const auto Cleanup = [this, &num_iterations, &high_priority_mode, &aggressive_mode](ImageId image_id) {
|
||||
if (num_iterations == 0) {
|
||||
return true;
|
||||
}
|
||||
--num_iterations;
|
||||
auto& image = slot_images[image_id];
|
||||
|
||||
// Never delete recently allocated sparse textures (within 3 frames)
|
||||
const bool is_recently_allocated = image.allocation_tick >= frame_tick - 3;
|
||||
if (is_recently_allocated && image.info.is_sparse) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (True(image.flags & ImageFlagBits::IsDecoding)) {
|
||||
// This image is still being decoded, deleting it will invalidate the slot
|
||||
// used by the async decoder thread.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prioritize large sparse textures for cleanup
|
||||
const bool is_large_sparse = lowmemorydevice &&
|
||||
image.info.is_sparse &&
|
||||
image.guest_size_bytes >= 256_MiB;
|
||||
|
||||
if (!aggressive_mode && !is_large_sparse &&
|
||||
True(image.flags & ImageFlagBits::CostlyLoad)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool must_download =
|
||||
image.IsSafeDownload() && False(image.flags & ImageFlagBits::BadOverlap);
|
||||
if (!high_priority_mode && !is_large_sparse && must_download) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (must_download && !is_large_sparse) {
|
||||
const bool must_download = image.IsSafeDownload() && False(image.flags & ImageFlagBits::BadOverlap);
|
||||
if (must_download && !image.info.is_sparse) {
|
||||
auto map = runtime.DownloadStagingBuffer(image.unswizzled_size_bytes);
|
||||
const auto copies = FixSmallVectorADL(FullDownloadCopies(image.info));
|
||||
image.DownloadMemory(map, copies);
|
||||
runtime.Finish();
|
||||
SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, map.mapped_span,
|
||||
swizzle_data_buffer);
|
||||
SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, map.mapped_span, swizzle_data_buffer);
|
||||
}
|
||||
|
||||
if (True(image.flags & ImageFlagBits::Tracked)) {
|
||||
UntrackImage(image, image_id);
|
||||
}
|
||||
UnregisterImage(image_id);
|
||||
DeleteImage(image_id, image.scale_tick > frame_tick + 5);
|
||||
|
||||
if (total_used_memory < critical_memory) {
|
||||
if (aggressive_mode) {
|
||||
// Sink the aggresiveness.
|
||||
DeleteImage(image_id, (frame_tick - image.scale_tick) > 5 || aggressive_mode);
|
||||
if (aggressive_mode && total_used_memory < critical_memory) {
|
||||
num_iterations >>= 2;
|
||||
aggressive_mode = false;
|
||||
return false;
|
||||
}
|
||||
if (high_priority_mode && total_used_memory < expected_memory) {
|
||||
num_iterations >>= 1;
|
||||
high_priority_mode = false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Aggressively clear massive sparse textures
|
||||
if (total_used_memory >= expected_memory) {
|
||||
lru_cache.ForEachItemBelow(frame_tick, [&](ImageId image_id) {
|
||||
auto& image = slot_images[image_id];
|
||||
// Only target sparse textures that are old enough
|
||||
if (lowmemorydevice &&
|
||||
image.info.is_sparse &&
|
||||
image.guest_size_bytes >= 256_MiB &&
|
||||
image.allocation_tick < frame_tick - 3) {
|
||||
LOG_DEBUG(HW_GPU, "GC targeting old sparse texture at 0x{:X} ({} MiB, age: {} frames)",
|
||||
image.gpu_addr, image.guest_size_bytes / (1024 * 1024),
|
||||
frame_tick - image.allocation_tick);
|
||||
return Cleanup(image_id);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
Configure(false);
|
||||
lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, Cleanup);
|
||||
|
||||
// If pressure is still too high, prune aggressively.
|
||||
if (total_used_memory >= critical_memory) {
|
||||
Configure(true);
|
||||
lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, Cleanup);
|
||||
|
|
@ -1196,9 +1136,6 @@ void TextureCache<P>::RefreshContents(Image& image, ImageId image_id) {
|
|||
}
|
||||
|
||||
image.flags &= ~ImageFlagBits::CpuModified;
|
||||
if( lowmemorydevice && image.info.format == PixelFormat::BC1_RGBA_UNORM && MapSizeBytes(image) >= 256_MiB ) {
|
||||
return;
|
||||
}
|
||||
|
||||
TrackImage(image, image_id);
|
||||
|
||||
|
|
@ -1619,39 +1556,6 @@ ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr,
|
|||
}
|
||||
}
|
||||
ASSERT_MSG(cpu_addr, "Tried to insert an image to an invalid gpu_addr=0x{:x}", gpu_addr);
|
||||
|
||||
// For large sparse textures, aggressively clean up old allocations at same address
|
||||
if (lowmemorydevice && info.is_sparse && CalculateGuestSizeInBytes(info) >= 256_MiB) {
|
||||
const auto alloc_it = image_allocs_table.find(gpu_addr);
|
||||
if (alloc_it != image_allocs_table.end()) {
|
||||
const ImageAllocId alloc_id = alloc_it->second;
|
||||
auto& alloc_images = slot_image_allocs[alloc_id].images;
|
||||
|
||||
// Collect old images at this address that were created more than 2 frames ago
|
||||
boost::container::small_vector<ImageId, 4> to_delete;
|
||||
for (ImageId old_image_id : alloc_images) {
|
||||
Image& old_image = slot_images[old_image_id];
|
||||
if (old_image.info.is_sparse &&
|
||||
old_image.gpu_addr == gpu_addr &&
|
||||
old_image.allocation_tick < frame_tick - 2) { // Try not to delete fresh textures
|
||||
to_delete.push_back(old_image_id);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete old images immediately
|
||||
for (ImageId old_id : to_delete) {
|
||||
Image& old_image = slot_images[old_id];
|
||||
LOG_DEBUG(HW_GPU, "Immediately deleting old sparse texture at 0x{:X} ({} MiB)",
|
||||
gpu_addr, old_image.guest_size_bytes / (1024 * 1024));
|
||||
if (True(old_image.flags & ImageFlagBits::Tracked)) {
|
||||
UntrackImage(old_image, old_id);
|
||||
}
|
||||
UnregisterImage(old_id);
|
||||
DeleteImage(old_id, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ImageId image_id = JoinImages(info, gpu_addr, *cpu_addr);
|
||||
const Image& image = slot_images[image_id];
|
||||
// Using "image.gpu_addr" instead of "gpu_addr" is important because it might be different
|
||||
|
|
@ -1667,27 +1571,6 @@ template <class P>
|
|||
ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DAddr cpu_addr) {
|
||||
ImageInfo new_info = info;
|
||||
const size_t size_bytes = CalculateGuestSizeInBytes(new_info);
|
||||
|
||||
// Proactive cleanup for large sparse texture allocations
|
||||
if (lowmemorydevice && new_info.is_sparse && size_bytes >= 256_MiB) {
|
||||
const u64 estimated_alloc_size = size_bytes;
|
||||
|
||||
if (total_used_memory + estimated_alloc_size >= critical_memory) {
|
||||
LOG_DEBUG(HW_GPU, "Large sparse texture allocation ({} MiB) - running aggressive GC. "
|
||||
"Current memory: {} MiB, Critical: {} MiB",
|
||||
size_bytes / (1024 * 1024),
|
||||
total_used_memory / (1024 * 1024),
|
||||
critical_memory / (1024 * 1024));
|
||||
RunGarbageCollector();
|
||||
|
||||
// If still over threshold after GC, try one more aggressive pass
|
||||
if (total_used_memory + estimated_alloc_size >= critical_memory) {
|
||||
LOG_DEBUG(HW_GPU, "Still critically low on memory, running second GC pass");
|
||||
RunGarbageCollector();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool broken_views = runtime.HasBrokenTextureViewFormats();
|
||||
const bool native_bgr = runtime.HasNativeBgr();
|
||||
join_overlap_ids.clear();
|
||||
|
|
|
|||
|
|
@ -478,7 +478,6 @@ private:
|
|||
u64 minimum_memory;
|
||||
u64 expected_memory;
|
||||
u64 critical_memory;
|
||||
bool lowmemorydevice = false;
|
||||
size_t gpu_unswizzle_maxsize = 0;
|
||||
size_t swizzle_chunk_size = 0;
|
||||
u32 swizzle_slices_per_batch = 0;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "common/logging/filter.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
#include "core/crypto/key_manager.h"
|
||||
#include "ui_configure_debug.h"
|
||||
#include "yuzu/configuration/configure_debug.h"
|
||||
#include "yuzu/debugger/console.h"
|
||||
|
|
@ -45,6 +46,7 @@ void ConfigureDebug::SetConfiguration() {
|
|||
ui->reporting_services->setChecked(Settings::values.reporting_services.GetValue());
|
||||
ui->dump_audio_commands->setChecked(Settings::values.dump_audio_commands.GetValue());
|
||||
ui->quest_flag->setChecked(Settings::values.quest_flag.GetValue());
|
||||
ui->use_dev_keys->setChecked(Settings::values.use_dev_keys.GetValue());
|
||||
ui->use_debug_asserts->setChecked(Settings::values.use_debug_asserts.GetValue());
|
||||
ui->use_auto_stub->setChecked(Settings::values.use_auto_stub.GetValue());
|
||||
ui->enable_all_controllers->setChecked(Settings::values.enable_all_controllers.GetValue());
|
||||
|
|
@ -105,6 +107,7 @@ void ConfigureDebug::ApplyConfiguration() {
|
|||
Settings::values.reporting_services = ui->reporting_services->isChecked();
|
||||
Settings::values.dump_audio_commands = ui->dump_audio_commands->isChecked();
|
||||
Settings::values.quest_flag = ui->quest_flag->isChecked();
|
||||
Settings::values.use_dev_keys = ui->use_dev_keys->isChecked();
|
||||
Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked();
|
||||
Settings::values.use_auto_stub = ui->use_auto_stub->isChecked();
|
||||
Settings::values.enable_all_controllers = ui->enable_all_controllers->isChecked();
|
||||
|
|
@ -126,6 +129,7 @@ void ConfigureDebug::ApplyConfiguration() {
|
|||
Common::Log::Filter filter;
|
||||
filter.ParseFilterString(Settings::values.log_filter.GetValue());
|
||||
Common::Log::SetGlobalFilter(filter);
|
||||
Core::Crypto::KeyManager::Instance().ReloadKeys();
|
||||
}
|
||||
|
||||
void ConfigureDebug::changeEvent(QEvent* event) {
|
||||
|
|
|
|||
|
|
@ -435,6 +435,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="use_dev_keys">
|
||||
<property name="text">
|
||||
<string>Use dev.keys</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="use_debug_asserts">
|
||||
<property name="text">
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
|
||||
|
|
@ -416,11 +416,9 @@ const QString ConfigureGraphics::TranslateVSyncMode(VkPresentModeKHR mode,
|
|||
}
|
||||
|
||||
int ConfigureGraphics::FindIndex(u32 enumeration, int value) const {
|
||||
for (u32 i = 0; i < combobox_translations.at(enumeration).size(); i++) {
|
||||
if (combobox_translations.at(enumeration)[i].first == static_cast<u32>(value)) {
|
||||
for (u32 i = 0; enumeration < combobox_translations.size() && i < combobox_translations.at(enumeration).size(); i++)
|
||||
if (combobox_translations.at(enumeration)[i].first == u32(value))
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -433,13 +431,11 @@ void ConfigureGraphics::ApplyConfiguration() {
|
|||
UpdateVsyncSetting();
|
||||
|
||||
Settings::values.vulkan_device.SetGlobal(true);
|
||||
if (Settings::IsConfiguringGlobal() ||
|
||||
(!Settings::IsConfiguringGlobal() && api_restore_global_button->isEnabled())) {
|
||||
auto backend = static_cast<Settings::RendererBackend>(
|
||||
combobox_translations
|
||||
.at(Settings::EnumMetadata<
|
||||
Settings::RendererBackend>::Index())[api_combobox->currentIndex()]
|
||||
.first);
|
||||
auto const index = Settings::EnumMetadata<Settings::RendererBackend>::Index();
|
||||
if (Settings::IsConfiguringGlobal() || (!Settings::IsConfiguringGlobal() && api_restore_global_button->isEnabled())) {
|
||||
auto backend = index >= combobox_translations.size() || size_t(api_combobox->currentIndex()) >= combobox_translations.at(index).size()
|
||||
? Settings::values.renderer_backend.GetValue()
|
||||
: Settings::RendererBackend(combobox_translations.at(index)[api_combobox->currentIndex()].first);
|
||||
switch (backend) {
|
||||
case Settings::RendererBackend::Vulkan:
|
||||
Settings::values.vulkan_device.SetGlobal(Settings::IsConfiguringGlobal());
|
||||
|
|
@ -507,13 +503,12 @@ void ConfigureGraphics::RetrieveVulkanDevices() {
|
|||
|
||||
Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const {
|
||||
const auto selected_backend = [&]() {
|
||||
if (!Settings::IsConfiguringGlobal() && !api_restore_global_button->isEnabled()) {
|
||||
auto const index = Settings::EnumMetadata<Settings::RendererBackend>::Index();
|
||||
if (!Settings::IsConfiguringGlobal() && !api_restore_global_button->isEnabled())
|
||||
return Settings::values.renderer_backend.GetValue(true);
|
||||
}
|
||||
return Settings::RendererBackend(
|
||||
combobox_translations.at(Settings::EnumMetadata<Settings::RendererBackend>::Index())
|
||||
.at(api_combobox->currentIndex())
|
||||
.first);
|
||||
return index >= combobox_translations.size() || size_t(api_combobox->currentIndex()) >= combobox_translations.at(index).size()
|
||||
? Settings::values.renderer_backend.GetValue()
|
||||
: Settings::RendererBackend(combobox_translations.at(index).at(api_combobox->currentIndex()).first);
|
||||
}();
|
||||
|
||||
if (selected_backend == Settings::RendererBackend::Vulkan && UISettings::values.has_broken_vulkan)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
|
|
@ -12,14 +12,13 @@
|
|||
#include "yuzu/configuration/configure_network.h"
|
||||
|
||||
ConfigureNetwork::ConfigureNetwork(const Core::System& system_, QWidget* parent)
|
||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureNetwork>()), system{system_} {
|
||||
: QWidget(parent)
|
||||
, ui(std::make_unique<Ui::ConfigureNetwork>())
|
||||
, system{system_}
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->network_interface->addItem(tr("None"));
|
||||
for (const auto& iface : Network::GetAvailableNetworkInterfaces()) {
|
||||
for (const auto& iface : Network::GetAvailableNetworkInterfaces())
|
||||
ui->network_interface->addItem(QString::fromStdString(iface.name));
|
||||
}
|
||||
|
||||
this->SetConfiguration();
|
||||
}
|
||||
|
||||
|
|
@ -44,13 +43,9 @@ void ConfigureNetwork::RetranslateUI() {
|
|||
|
||||
void ConfigureNetwork::SetConfiguration() {
|
||||
const bool runtime_lock = !system.IsPoweredOn();
|
||||
|
||||
const std::string& network_interface = Settings::values.network_interface.GetValue();
|
||||
const bool& airplane_mode = Settings::values.airplane_mode.GetValue();
|
||||
|
||||
auto const network_interface = Settings::values.network_interface.GetValue();
|
||||
auto const airplane_mode = Settings::values.airplane_mode.GetValue();
|
||||
ui->network_interface->setCurrentText(QString::fromStdString(network_interface));
|
||||
ui->network_interface->setEnabled(runtime_lock);
|
||||
|
||||
ui->airplane_mode->setChecked(airplane_mode);
|
||||
ui->network_interface->setEnabled(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,6 +139,8 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
|
|||
|
||||
#include "core/perf_stats.h"
|
||||
|
||||
#include "core/crypto/key_manager.h"
|
||||
|
||||
// Input //
|
||||
#include "hid_core/hid_core.h"
|
||||
#include "hid_core/frontend/emulated_controller.h"
|
||||
|
|
@ -564,6 +566,9 @@ MainWindow::MainWindow(bool has_broken_vulkan)
|
|||
// Check for orphaned profiles and reset profile data if necessary
|
||||
QtCommon::Content::FixProfiles();
|
||||
|
||||
if (Settings::values.use_dev_keys.GetValue()) {
|
||||
Core::Crypto::KeyManager::Instance().ReloadKeys();
|
||||
}
|
||||
game_list->LoadCompatibilityList();
|
||||
game_list->PopulateAsync(UISettings::values.game_dirs);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ Check a specific package or packages for updates.
|
|||
Options:
|
||||
-n, --dry-run Do not update the package if it has an update available
|
||||
-a, --all Operate on all packages in this project.
|
||||
-c, --commit Automatically generate a commit message
|
||||
|
||||
EOF
|
||||
|
||||
|
|
@ -38,6 +39,7 @@ while :; do
|
|||
case "$char" in
|
||||
a) ALL=1 ;;
|
||||
n) UPDATE=false ;;
|
||||
c) COMMIT=true ;;
|
||||
h) usage ;;
|
||||
*) die "Invalid option -$char" ;;
|
||||
esac
|
||||
|
|
@ -46,6 +48,7 @@ while :; do
|
|||
--dry-run) UPDATE=false ;;
|
||||
--all) ALL=1 ;;
|
||||
--help) usage ;;
|
||||
--commit) COMMIT=true ;;
|
||||
"$0") break ;;
|
||||
"") break ;;
|
||||
*) packages="$packages $1" ;;
|
||||
|
|
@ -56,6 +59,7 @@ done
|
|||
|
||||
[ "$ALL" != 1 ] || packages="${LIBS:-$packages}"
|
||||
: "${UPDATE:=true}"
|
||||
: "${COMMIT:=false}"
|
||||
[ -n "$packages" ] || usage
|
||||
|
||||
for pkg in $packages; do
|
||||
|
|
@ -93,6 +97,9 @@ for pkg in $packages; do
|
|||
|
||||
filter_out yotta # mbedtls
|
||||
|
||||
# ????????????????????????????????
|
||||
filter_out vksc
|
||||
|
||||
# ignore betas/alphas (remove if needed)
|
||||
filter_out alpha
|
||||
filter_out beta
|
||||
|
|
@ -119,19 +126,35 @@ for pkg in $packages; do
|
|||
else
|
||||
NEW_GIT_VERSION=$(echo "$LATEST" | sed "s/$VERSION_PREFIX//g")
|
||||
fi
|
||||
else
|
||||
NEW_GIT_VERSION="$LATEST"
|
||||
fi
|
||||
|
||||
_commit="$_commit
|
||||
* $PACKAGE: $GIT_VERSION -> $NEW_GIT_VERSION"
|
||||
|
||||
echo "-- * Version $LATEST available, current is $TAG"
|
||||
|
||||
if [ "$UPDATE" = "true" ]; then
|
||||
if [ "$HAS_REPLACE" = "true" ]; then
|
||||
NEW_JSON=$(echo "$JSON" | jq ".git_version = \"$NEW_GIT_VERSION\"")
|
||||
else
|
||||
NEW_JSON=$(echo "$JSON" | jq ".tag = \"$LATEST\"")
|
||||
NEW_JSON=$(echo "$JSON" | jq ".tag = \"$NEW_GIT_VERSION\"")
|
||||
fi
|
||||
|
||||
"$SCRIPTS"/util/replace.sh "$PACKAGE" "$NEW_JSON"
|
||||
|
||||
QUIET=true "$SCRIPTS"/util/fix-hash.sh
|
||||
echo "-- * -- Updating hash"
|
||||
|
||||
export UPDATE
|
||||
QUIET=true "$SCRIPTS"/util/fix-hash.sh "$PACKAGE"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$UPDATE" = "true" ] && [ "$COMMIT" = "true" ] && [ -n "$_commit" ]; then
|
||||
for file in $CPMFILES; do
|
||||
git add "$file"
|
||||
done
|
||||
git commit -m "Update dependencies
|
||||
$_commit"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -3,9 +3,15 @@
|
|||
# SPDX-FileCopyrightText: Copyright 2026 crueter
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
|
||||
: "${PACKAGE:=$1}"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
# re-read json files
|
||||
# shellcheck disable=SC2016
|
||||
PACKAGES=$(echo "$CPMFILES" | xargs jq -s 'reduce .[] as $item ({}; . * $item)')
|
||||
export PACKAGES
|
||||
|
||||
. "$SCRIPTS"/vars.sh
|
||||
|
||||
[ "$CI" = null ] || exit 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue