summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/hex_util.cpp7
-rw-r--r--src/common/hex_util.h16
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/constants.cpp17
-rw-r--r--src/core/constants.h17
-rw-r--r--src/core/crypto/key_manager.cpp4
-rw-r--r--src/core/file_sys/card_image.cpp46
-rw-r--r--src/core/file_sys/ips_layer.cpp3
-rw-r--r--src/core/file_sys/nca_metadata.h9
-rw-r--r--src/core/file_sys/patch_manager.cpp8
-rw-r--r--src/core/file_sys/registered_cache.cpp14
-rw-r--r--src/core/file_sys/submission_package.cpp13
-rw-r--r--src/core/file_sys/xts_archive.cpp2
-rw-r--r--src/core/hle/kernel/process.cpp18
-rw-r--r--src/core/hle/kernel/process.h13
-rw-r--r--src/core/hle/kernel/svc.cpp26
-rw-r--r--src/core/hle/kernel/vm_manager.cpp6
-rw-r--r--src/core/hle/kernel/vm_manager.h2
-rw-r--r--src/core/hle/service/acc/acc.cpp20
-rw-r--r--src/core/hle/service/am/applets/general_backend.cpp12
-rw-r--r--src/core/hle/service/ldr/ldr.cpp2
-rw-r--r--src/core/loader/nso.cpp4
-rw-r--r--src/video_core/engines/kepler_compute.h7
-rw-r--r--src/video_core/memory_manager.h4
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp31
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp49
-rw-r--r--src/video_core/shader/decode/other.cpp18
-rw-r--r--src/video_core/shader/node.h7
-rw-r--r--src/yuzu/applets/profile_select.cpp15
-rw-r--r--src/yuzu/configuration/configure_audio.cpp33
-rw-r--r--src/yuzu/configuration/configure_audio.h7
-rw-r--r--src/yuzu/configuration/configure_debug.cpp12
-rw-r--r--src/yuzu/configuration/configure_debug.h3
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp60
-rw-r--r--src/yuzu/configuration/configure_dialog.h4
-rw-r--r--src/yuzu/configuration/configure_gamelist.cpp1
-rw-r--r--src/yuzu/configuration/configure_general.cpp12
-rw-r--r--src/yuzu/configuration/configure_general.h3
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp12
-rw-r--r--src/yuzu/configuration/configure_graphics.h3
-rw-r--r--src/yuzu/configuration/configure_hotkeys.cpp21
-rw-r--r--src/yuzu/configuration/configure_hotkeys.h4
-rw-r--r--src/yuzu/configuration/configure_input.cpp46
-rw-r--r--src/yuzu/configuration/configure_input.h6
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp13
-rw-r--r--src/yuzu/configuration/configure_input_player.h3
-rw-r--r--src/yuzu/configuration/configure_input_simple.cpp12
-rw-r--r--src/yuzu/configuration/configure_input_simple.h3
-rw-r--r--src/yuzu/configuration/configure_mouse_advanced.cpp12
-rw-r--r--src/yuzu/configuration/configure_mouse_advanced.h3
-rw-r--r--src/yuzu/configuration/configure_per_general.cpp12
-rw-r--r--src/yuzu/configuration/configure_per_general.h3
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp21
-rw-r--r--src/yuzu/configuration/configure_profile_manager.h3
-rw-r--r--src/yuzu/configuration/configure_system.cpp12
-rw-r--r--src/yuzu/configuration/configure_system.h3
-rw-r--r--src/yuzu/configuration/configure_touchscreen_advanced.cpp12
-rw-r--r--src/yuzu/configuration/configure_touchscreen_advanced.h3
-rw-r--r--src/yuzu/configuration/configure_web.cpp38
-rw-r--r--src/yuzu/configuration/configure_web.h4
60 files changed, 585 insertions, 191 deletions
diff --git a/src/common/hex_util.cpp b/src/common/hex_util.cpp
index 5b63f9e81..c2f6cf0f6 100644
--- a/src/common/hex_util.cpp
+++ b/src/common/hex_util.cpp
@@ -30,13 +30,6 @@ std::vector<u8> HexStringToVector(std::string_view str, bool little_endian) {
return out;
}
-std::string HexVectorToString(const std::vector<u8>& vector, bool upper) {
- std::string out;
- for (u8 c : vector)
- out += fmt::format(upper ? "{:02X}" : "{:02x}", c);
- return out;
-}
-
std::array<u8, 16> operator""_array16(const char* str, std::size_t len) {
if (len != 32) {
LOG_ERROR(Common,
diff --git a/src/common/hex_util.h b/src/common/hex_util.h
index 68f003cb6..bb4736f96 100644
--- a/src/common/hex_util.h
+++ b/src/common/hex_util.h
@@ -7,6 +7,7 @@
#include <array>
#include <cstddef>
#include <string>
+#include <type_traits>
#include <vector>
#include <fmt/format.h>
#include "common/common_types.h"
@@ -30,13 +31,20 @@ std::array<u8, Size> HexStringToArray(std::string_view str) {
return out;
}
-std::string HexVectorToString(const std::vector<u8>& vector, bool upper = true);
+template <typename ContiguousContainer>
+std::string HexToString(const ContiguousContainer& data, bool upper = true) {
+ static_assert(std::is_same_v<typename ContiguousContainer::value_type, u8>,
+ "Underlying type within the contiguous container must be u8.");
+
+ constexpr std::size_t pad_width = 2;
-template <std::size_t Size>
-std::string HexArrayToString(std::array<u8, Size> array, bool upper = true) {
std::string out;
- for (u8 c : array)
+ out.reserve(std::size(data) * pad_width);
+
+ for (const u8 c : data) {
out += fmt::format(upper ? "{:02X}" : "{:02x}", c);
+ }
+
return out;
}
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 6bf512e12..a2e2e976e 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -5,6 +5,8 @@ add_library(core STATIC
arm/exclusive_monitor.h
arm/unicorn/arm_unicorn.cpp
arm/unicorn/arm_unicorn.h
+ constants.cpp
+ constants.h
core.cpp
core.h
core_cpu.cpp
diff --git a/src/core/constants.cpp b/src/core/constants.cpp
new file mode 100644
index 000000000..dccb3e03c
--- /dev/null
+++ b/src/core/constants.cpp
@@ -0,0 +1,17 @@
+// Copyright 2019 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/constants.h"
+
+namespace Core::Constants {
+const std::array<u8, 107> ACCOUNT_BACKUP_JPEG{{
+ 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
+ 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x06, 0x06, 0x05,
+ 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a, 0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e,
+ 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13,
+ 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10, 0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01,
+ 0x01, 0x01, 0x11, 0x00, 0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08,
+ 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,
+}};
+}
diff --git a/src/core/constants.h b/src/core/constants.h
new file mode 100644
index 000000000..6d0ec022a
--- /dev/null
+++ b/src/core/constants.h
@@ -0,0 +1,17 @@
+// Copyright 2019 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/common_types.h"
+
+// This is to consolidate system-wide constants that are used by multiple components of yuzu.
+// This is especially to prevent the case of something in frontend duplicating a constexpr array or
+// directly including some service header for the sole purpose of data.
+namespace Core::Constants {
+
+// ACC Service - Blank JPEG used as user icon in absentia of real one.
+extern const std::array<u8, 107> ACCOUNT_BACKUP_JPEG;
+
+} // namespace Core::Constants
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index dc006e2bb..6dd633363 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -572,7 +572,7 @@ void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname,
<< "# If you are experiencing issues involving keys, it may help to delete this file\n";
}
- file << fmt::format("\n{} = {}", keyname, Common::HexArrayToString(key));
+ file << fmt::format("\n{} = {}", keyname, Common::HexToString(key));
AttemptLoadKeyFile(yuzu_keys_dir, yuzu_keys_dir, filename, category == KeyCategory::Title);
}
@@ -583,7 +583,7 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) {
Key128 rights_id;
std::memcpy(rights_id.data(), &field2, sizeof(u64));
std::memcpy(rights_id.data() + sizeof(u64), &field1, sizeof(u64));
- WriteKeyToFile(KeyCategory::Title, Common::HexArrayToString(rights_id), key);
+ WriteKeyToFile(KeyCategory::Title, Common::HexToString(rights_id), key);
}
auto category = KeyCategory::Standard;
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp
index 2c145bd09..626ed0042 100644
--- a/src/core/file_sys/card_image.cpp
+++ b/src/core/file_sys/card_image.cpp
@@ -18,11 +18,16 @@
namespace FileSys {
-constexpr std::array<const char*, 0x4> partition_names = {"update", "normal", "secure", "logo"};
+constexpr std::array partition_names{
+ "update",
+ "normal",
+ "secure",
+ "logo",
+};
XCI::XCI(VirtualFile file_)
: file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA},
- partitions(0x4) {
+ partitions(partition_names.size()) {
if (file->ReadObject(&header) != sizeof(GamecardHeader)) {
status = Loader::ResultStatus::ErrorBadXCIHeader;
return;
@@ -43,23 +48,24 @@ XCI::XCI(VirtualFile file_)
for (XCIPartition partition :
{XCIPartition::Update, XCIPartition::Normal, XCIPartition::Secure, XCIPartition::Logo}) {
- auto raw = main_hfs.GetFile(partition_names[static_cast<std::size_t>(partition)]);
- if (raw != nullptr)
- partitions[static_cast<std::size_t>(partition)] =
- std::make_shared<PartitionFilesystem>(raw);
+ const auto partition_idx = static_cast<std::size_t>(partition);
+ auto raw = main_hfs.GetFile(partition_names[partition_idx]);
+
+ if (raw != nullptr) {
+ partitions[partition_idx] = std::make_shared<PartitionFilesystem>(std::move(raw));
+ }
}
secure_partition = std::make_shared<NSP>(
main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)]));
- const auto secure_ncas = secure_partition->GetNCAsCollapsed();
- std::copy(secure_ncas.begin(), secure_ncas.end(), std::back_inserter(ncas));
-
+ ncas = secure_partition->GetNCAsCollapsed();
program =
secure_partition->GetNCA(secure_partition->GetProgramTitleID(), ContentRecordType::Program);
program_nca_status = secure_partition->GetProgramStatus(secure_partition->GetProgramTitleID());
- if (program_nca_status == Loader::ResultStatus::ErrorNSPMissingProgramNCA)
+ if (program_nca_status == Loader::ResultStatus::ErrorNSPMissingProgramNCA) {
program_nca_status = Loader::ResultStatus::ErrorXCIMissingProgramNCA;
+ }
auto result = AddNCAFromPartition(XCIPartition::Update);
if (result != Loader::ResultStatus::Success) {
@@ -147,8 +153,9 @@ std::shared_ptr<NCA> XCI::GetNCAByType(NCAContentType type) const {
VirtualFile XCI::GetNCAFileByType(NCAContentType type) const {
auto nca = GetNCAByType(type);
- if (nca != nullptr)
+ if (nca != nullptr) {
return nca->GetBaseFile();
+ }
return nullptr;
}
@@ -169,17 +176,22 @@ VirtualDir XCI::GetParentDirectory() const {
}
Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) {
- if (partitions[static_cast<std::size_t>(part)] == nullptr) {
+ const auto partition_index = static_cast<std::size_t>(part);
+ const auto& partition = partitions[partition_index];
+
+ if (partition == nullptr) {
return Loader::ResultStatus::ErrorXCIMissingPartition;
}
- for (const VirtualFile& file : partitions[static_cast<std::size_t>(part)]->GetFiles()) {
- if (file->GetExtension() != "nca")
+ for (const VirtualFile& file : partition->GetFiles()) {
+ if (file->GetExtension() != "nca") {
continue;
+ }
+
auto nca = std::make_shared<NCA>(file, nullptr, 0, keys);
- // TODO(DarkLordZach): Add proper Rev1+ Support
- if (nca->IsUpdate())
+ if (nca->IsUpdate()) {
continue;
+ }
if (nca->GetType() == NCAContentType::Program) {
program_nca_status = nca->GetStatus();
}
@@ -188,7 +200,7 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) {
} else {
const u16 error_id = static_cast<u16>(nca->GetStatus());
LOG_CRITICAL(Loader, "Could not load NCA {}/{}, failed with error code {:04X} ({})",
- partition_names[static_cast<std::size_t>(part)], nca->GetName(), error_id,
+ partition_names[partition_index], nca->GetName(), error_id,
nca->GetStatus());
}
}
diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp
index 485c4913a..a08a70efd 100644
--- a/src/core/file_sys/ips_layer.cpp
+++ b/src/core/file_sys/ips_layer.cpp
@@ -287,7 +287,6 @@ void IPSwitchCompiler::Parse() {
} else {
// hex replacement
const auto value = patch_line.substr(9);
- replace.reserve(value.size() / 2);
replace = Common::HexStringToVector(value, is_little_endian);
}
@@ -295,7 +294,7 @@ void IPSwitchCompiler::Parse() {
LOG_INFO(Loader,
"[IPSwitchCompiler ('{}')] - Patching value at offset 0x{:08X} "
"with byte string '{}'",
- patch_text->GetName(), offset, Common::HexVectorToString(replace));
+ patch_text->GetName(), offset, Common::HexToString(replace));
}
patch.records.insert_or_assign(offset, std::move(replace));
diff --git a/src/core/file_sys/nca_metadata.h b/src/core/file_sys/nca_metadata.h
index 50bf38471..84d5cd1e0 100644
--- a/src/core/file_sys/nca_metadata.h
+++ b/src/core/file_sys/nca_metadata.h
@@ -4,6 +4,7 @@
#pragma once
+#include <array>
#include <memory>
#include <vector>
#include "common/common_funcs.h"
@@ -69,11 +70,15 @@ struct CNMTHeader {
u64_le title_id;
u32_le title_version;
TitleType type;
- INSERT_PADDING_BYTES(1);
+ u8 reserved;
u16_le table_offset;
u16_le number_content_entries;
u16_le number_meta_entries;
- INSERT_PADDING_BYTES(12);
+ u8 attributes;
+ std::array<u8, 2> reserved2;
+ u8 is_committed;
+ u32_le required_download_system_version;
+ std::array<u8, 4> reserved3;
};
static_assert(sizeof(CNMTHeader) == 0x20, "CNMTHeader has incorrect size.");
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index 78dbadee3..da823c37b 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -142,7 +142,7 @@ std::vector<VirtualFile> PatchManager::CollectPatches(const std::vector<VirtualD
if (!compiler.IsValid())
continue;
- auto this_build_id = Common::HexArrayToString(compiler.GetBuildID());
+ auto this_build_id = Common::HexToString(compiler.GetBuildID());
this_build_id =
this_build_id.substr(0, this_build_id.find_last_not_of('0') + 1);
@@ -168,7 +168,7 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st
return nso;
}
- const auto build_id_raw = Common::HexArrayToString(header.build_id);
+ const auto build_id_raw = Common::HexToString(header.build_id);
const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1);
if (Settings::values.dump_nso) {
@@ -219,7 +219,7 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st
}
bool PatchManager::HasNSOPatch(const std::array<u8, 32>& build_id_) const {
- const auto build_id_raw = Common::HexArrayToString(build_id_);
+ const auto build_id_raw = Common::HexToString(build_id_);
const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1);
LOG_INFO(Loader, "Querying NSO patch existence for build_id={}", build_id);
@@ -235,7 +235,7 @@ bool PatchManager::HasNSOPatch(const std::array<u8, 32>& build_id_) const {
static std::optional<CheatList> ReadCheatFileFromFolder(const Core::System& system, u64 title_id,
const std::array<u8, 0x20>& build_id_,
const VirtualDir& base_path, bool upper) {
- const auto build_id_raw = Common::HexArrayToString(build_id_, upper);
+ const auto build_id_raw = Common::HexToString(build_id_, upper);
const auto build_id = build_id_raw.substr(0, sizeof(u64) * 2);
const auto file = base_path->GetFile(fmt::format("{}.txt", build_id));
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index 3946ff871..58917e094 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -53,13 +53,14 @@ static bool FollowsNcaIdFormat(std::string_view name) {
static std::string GetRelativePathFromNcaID(const std::array<u8, 16>& nca_id, bool second_hex_upper,
bool within_two_digit) {
- if (!within_two_digit)
- return fmt::format("/{}.nca", Common::HexArrayToString(nca_id, second_hex_upper));
+ if (!within_two_digit) {
+ return fmt::format("/{}.nca", Common::HexToString(nca_id, second_hex_upper));
+ }
Core::Crypto::SHA256Hash hash{};
mbedtls_sha256(nca_id.data(), nca_id.size(), hash.data(), 0);
return fmt::format("/000000{:02X}/{}.nca", hash[0],
- Common::HexArrayToString(nca_id, second_hex_upper));
+ Common::HexToString(nca_id, second_hex_upper));
}
static std::string GetCNMTName(TitleType type, u64 title_id) {
@@ -376,10 +377,11 @@ std::vector<ContentProviderEntry> RegisteredCache::ListEntriesFilter(
}
static std::shared_ptr<NCA> GetNCAFromNSPForID(const NSP& nsp, const NcaID& id) {
- const auto file = nsp.GetFile(fmt::format("{}.nca", Common::HexArrayToString(id, false)));
- if (file == nullptr)
+ auto file = nsp.GetFile(fmt::format("{}.nca", Common::HexToString(id, false)));
+ if (file == nullptr) {
return nullptr;
- return std::make_shared<NCA>(file);
+ }
+ return std::make_shared<NCA>(std::move(file));
}
InstallResult RegisteredCache::InstallEntry(const XCI& xci, bool overwrite_if_exists,
diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp
index c69caae0f..d0428a457 100644
--- a/src/core/file_sys/submission_package.cpp
+++ b/src/core/file_sys/submission_package.cpp
@@ -235,16 +235,18 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
const auto section0 = nca->GetSubdirectories()[0];
for (const auto& inner_file : section0->GetFiles()) {
- if (inner_file->GetExtension() != "cnmt")
+ if (inner_file->GetExtension() != "cnmt") {
continue;
+ }
const CNMT cnmt(inner_file);
auto& ncas_title = ncas[cnmt.GetTitleID()];
ncas_title[{cnmt.GetType(), ContentRecordType::Meta}] = nca;
for (const auto& rec : cnmt.GetContentRecords()) {
- const auto id_string = Common::HexArrayToString(rec.nca_id, false);
- const auto next_file = pfs->GetFile(fmt::format("{}.nca", id_string));
+ const auto id_string = Common::HexToString(rec.nca_id, false);
+ auto next_file = pfs->GetFile(fmt::format("{}.nca", id_string));
+
if (next_file == nullptr) {
LOG_WARNING(Service_FS,
"NCA with ID {}.nca is listed in content metadata, but cannot "
@@ -253,9 +255,10 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
continue;
}
- auto next_nca = std::make_shared<NCA>(next_file, nullptr, 0, keys);
- if (next_nca->GetType() == NCAContentType::Program)
+ auto next_nca = std::make_shared<NCA>(std::move(next_file), nullptr, 0, keys);
+ if (next_nca->GetType() == NCAContentType::Program) {
program_status[cnmt.GetTitleID()] = next_nca->GetStatus();
+ }
if (next_nca->GetStatus() == Loader::ResultStatus::Success ||
(next_nca->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS &&
(cnmt.GetTitleID() & 0x800) != 0)) {
diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp
index eec51c64e..4bc5cb2ee 100644
--- a/src/core/file_sys/xts_archive.cpp
+++ b/src/core/file_sys/xts_archive.cpp
@@ -66,7 +66,7 @@ NAX::NAX(VirtualFile file_, std::array<u8, 0x10> nca_id)
Core::Crypto::SHA256Hash hash{};
mbedtls_sha256(nca_id.data(), nca_id.size(), hash.data(), 0);
status = Parse(fmt::format("/registered/000000{:02X}/{}.nca", hash[0],
- Common::HexArrayToString(nca_id, false)));
+ Common::HexToString(nca_id, false)));
}
NAX::~NAX() = default;
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 0775a89fb..2b81a8d4f 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -48,7 +48,7 @@ void SetupMainThread(Process& owner_process, KernelCore& kernel, u32 priority) {
}
} // Anonymous namespace
-SharedPtr<Process> Process::Create(Core::System& system, std::string&& name) {
+SharedPtr<Process> Process::Create(Core::System& system, std::string name) {
auto& kernel = system.Kernel();
SharedPtr<Process> process(new Process(system));
@@ -72,10 +72,26 @@ SharedPtr<ResourceLimit> Process::GetResourceLimit() const {
return resource_limit;
}
+u64 Process::GetTotalPhysicalMemoryAvailable() const {
+ return vm_manager.GetTotalPhysicalMemoryAvailable();
+}
+
+u64 Process::GetTotalPhysicalMemoryAvailableWithoutMmHeap() const {
+ // TODO: Subtract the personal heap size from this when the
+ // personal heap is implemented.
+ return GetTotalPhysicalMemoryAvailable();
+}
+
u64 Process::GetTotalPhysicalMemoryUsed() const {
return vm_manager.GetCurrentHeapSize() + main_thread_stack_size + code_memory_size;
}
+u64 Process::GetTotalPhysicalMemoryUsedWithoutMmHeap() const {
+ // TODO: Subtract the personal heap size from this when the
+ // personal heap is implemented.
+ return GetTotalPhysicalMemoryUsed();
+}
+
void Process::RegisterThread(const Thread* thread) {
thread_list.push_back(thread);
}
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index f027fafa3..29e016983 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -75,7 +75,7 @@ public:
static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4;
- static SharedPtr<Process> Create(Core::System& system, std::string&& name);
+ static SharedPtr<Process> Create(Core::System& system, std::string name);
std::string GetTypeName() const override {
return "Process";
@@ -186,9 +186,20 @@ public:
return random_entropy.at(index);
}
+ /// Retrieves the total physical memory available to this process in bytes.
+ u64 GetTotalPhysicalMemoryAvailable() const;
+
+ /// Retrieves the total physical memory available to this process in bytes,
+ /// without the size of the personal heap added to it.
+ u64 GetTotalPhysicalMemoryAvailableWithoutMmHeap() const;
+
/// Retrieves the total physical memory used by this process in bytes.
u64 GetTotalPhysicalMemoryUsed() const;
+ /// Retrieves the total physical memory used by this process in bytes,
+ /// without the size of the personal heap added to it.
+ u64 GetTotalPhysicalMemoryUsedWithoutMmHeap() const;
+
/// Gets the list of all threads created with this process as their owner.
const std::list<const Thread*>& GetThreadList() const {
return thread_list;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 5a5851f66..f9c606bc5 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -710,13 +710,13 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
MapRegionSize = 3,
HeapRegionBaseAddr = 4,
HeapRegionSize = 5,
- TotalMemoryUsage = 6,
+ TotalPhysicalMemoryAvailable = 6,
TotalPhysicalMemoryUsed = 7,
IsCurrentProcessBeingDebugged = 8,
RegisterResourceLimit = 9,
IdleTickCount = 10,
RandomEntropy = 11,
- PerformanceCounter = 0xF0000002,
+ ThreadTickCount = 0xF0000002,
// 2.0.0+
ASLRRegionBaseAddr = 12,
ASLRRegionSize = 13,
@@ -730,7 +730,9 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
PrivilegedProcessId = 19,
// 5.0.0+
UserExceptionContextAddr = 20,
- ThreadTickCount = 0xF0000002,
+ // 6.0.0+
+ TotalPhysicalMemoryAvailableWithoutMmHeap = 21,
+ TotalPhysicalMemoryUsedWithoutMmHeap = 22,
};
const auto info_id_type = static_cast<GetInfoType>(info_id);
@@ -746,12 +748,14 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
case GetInfoType::ASLRRegionSize:
case GetInfoType::NewMapRegionBaseAddr:
case GetInfoType::NewMapRegionSize:
- case GetInfoType::TotalMemoryUsage:
+ case GetInfoType::TotalPhysicalMemoryAvailable:
case GetInfoType::TotalPhysicalMemoryUsed:
case GetInfoType::IsVirtualAddressMemoryEnabled:
case GetInfoType::PersonalMmHeapUsage:
case GetInfoType::TitleId:
- case GetInfoType::UserExceptionContextAddr: {
+ case GetInfoType::UserExceptionContextAddr:
+ case GetInfoType::TotalPhysicalMemoryAvailableWithoutMmHeap:
+ case GetInfoType::TotalPhysicalMemoryUsedWithoutMmHeap: {
if (info_sub_id != 0) {
return ERR_INVALID_ENUM_VALUE;
}
@@ -804,8 +808,8 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
*result = process->VMManager().GetNewMapRegionSize();
return RESULT_SUCCESS;
- case GetInfoType::TotalMemoryUsage:
- *result = process->VMManager().GetTotalMemoryUsage();
+ case GetInfoType::TotalPhysicalMemoryAvailable:
+ *result = process->GetTotalPhysicalMemoryAvailable();
return RESULT_SUCCESS;
case GetInfoType::TotalPhysicalMemoryUsed:
@@ -826,6 +830,14 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
*result = 0;
return RESULT_SUCCESS;
+ case GetInfoType::TotalPhysicalMemoryAvailableWithoutMmHeap:
+ *result = process->GetTotalPhysicalMemoryAvailable();
+ return RESULT_SUCCESS;
+
+ case GetInfoType::TotalPhysicalMemoryUsedWithoutMmHeap:
+ *result = process->GetTotalPhysicalMemoryUsedWithoutMmHeap();
+ return RESULT_SUCCESS;
+
default:
break;
}
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 48b13cfdd..c929c2a52 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -68,9 +68,7 @@ VMManager::VMManager(Core::System& system) : system{system} {
Reset(FileSys::ProgramAddressSpaceType::Is39Bit);
}
-VMManager::~VMManager() {
- Reset(FileSys::ProgramAddressSpaceType::Is39Bit);
-}
+VMManager::~VMManager() = default;
void VMManager::Reset(FileSys::ProgramAddressSpaceType type) {
Clear();
@@ -758,7 +756,7 @@ VMManager::CheckResults VMManager::CheckRangeState(VAddr address, u64 size, Memo
std::make_tuple(initial_state, initial_permissions, initial_attributes & ~ignore_mask));
}
-u64 VMManager::GetTotalMemoryUsage() const {
+u64 VMManager::GetTotalPhysicalMemoryAvailable() const {
LOG_WARNING(Kernel, "(STUBBED) called");
return 0xF8000000;
}
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index ec84d9a70..dfbf7a894 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -499,7 +499,7 @@ public:
void LogLayout() const;
/// Gets the total memory usage, used by svcGetInfo
- u64 GetTotalMemoryUsage() const;
+ u64 GetTotalPhysicalMemoryAvailable() const;
/// Gets the address space base address
VAddr GetAddressSpaceBaseAddress() const;
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 86bf53d08..cb66e344b 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -10,6 +10,7 @@
#include "common/logging/log.h"
#include "common/string_util.h"
#include "common/swap.h"
+#include "core/constants.h"
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/acc/acc.h"
@@ -21,19 +22,6 @@
namespace Service::Account {
-// Smallest JPEG https://github.com/mathiasbynens/small/blob/master/jpeg.jpg
-// used as a backup should the one on disk not exist
-constexpr u32 backup_jpeg_size = 107;
-constexpr std::array<u8, backup_jpeg_size> backup_jpeg{{
- 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
- 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x06, 0x06, 0x05,
- 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a, 0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e,
- 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13,
- 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10, 0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01,
- 0x01, 0x01, 0x11, 0x00, 0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08,
- 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,
-}};
-
static std::string GetImagePath(Common::UUID uuid) {
return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) +
"/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg";
@@ -101,8 +89,8 @@ private:
if (!image.IsOpen()) {
LOG_WARNING(Service_ACC,
"Failed to load user provided image! Falling back to built-in backup...");
- ctx.WriteBuffer(backup_jpeg);
- rb.Push<u32>(backup_jpeg_size);
+ ctx.WriteBuffer(Core::Constants::ACCOUNT_BACKUP_JPEG);
+ rb.Push<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size());
return;
}
@@ -124,7 +112,7 @@ private:
if (!image.IsOpen()) {
LOG_WARNING(Service_ACC,
"Failed to load user provided image! Falling back to built-in backup...");
- rb.Push<u32>(backup_jpeg_size);
+ rb.Push<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size());
} else {
rb.Push<u32>(SanitizeJPEGSize(image.GetSize()));
}
diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp
index c591b9ac2..76fc8906d 100644
--- a/src/core/hle/service/am/applets/general_backend.cpp
+++ b/src/core/hle/service/am/applets/general_backend.cpp
@@ -2,7 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <string>
+#include <string_view>
#include "common/assert.h"
#include "common/hex_util.h"
@@ -16,21 +16,21 @@
namespace Service::AM::Applets {
-static void LogCurrentStorage(AppletDataBroker& broker, std::string prefix) {
+static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) {
std::unique_ptr<IStorage> storage = broker.PopNormalDataToApplet();
for (; storage != nullptr; storage = broker.PopNormalDataToApplet()) {
const auto data = storage->GetData();
LOG_INFO(Service_AM,
- "called (STUBBED), during {} recieved normal data with size={:08X}, data={}",
- prefix, data.size(), Common::HexVectorToString(data));
+ "called (STUBBED), during {} received normal data with size={:08X}, data={}",
+ prefix, data.size(), Common::HexToString(data));
}
storage = broker.PopInteractiveDataToApplet();
for (; storage != nullptr; storage = broker.PopInteractiveDataToApplet()) {
const auto data = storage->GetData();
LOG_INFO(Service_AM,
- "called (STUBBED), during {} recieved interactive data with size={:08X}, data={}",
- prefix, data.size(), Common::HexVectorToString(data));
+ "called (STUBBED), during {} received interactive data with size={:08X}, data={}",
+ prefix, data.size(), Common::HexToString(data));
}
}
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index 5af925515..b839303ac 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -310,7 +310,7 @@ public:
if (!IsValidNROHash(hash)) {
LOG_ERROR(Service_LDR,
"NRO hash is not present in any currently loaded NRRs (hash={})!",
- Common::HexArrayToString(hash));
+ Common::HexToString(hash));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERROR_MISSING_NRR_HASH);
return;
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 62c090353..80090b792 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -152,8 +152,8 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
auto& system = Core::System::GetInstance();
const auto cheats = pm->CreateCheatList(system, nso_header.build_id);
if (!cheats.empty()) {
- system.RegisterCheatList(cheats, Common::HexArrayToString(nso_header.build_id),
- load_base, load_base + program_image.size());
+ system.RegisterCheatList(cheats, Common::HexToString(nso_header.build_id), load_base,
+ load_base + program_image.size());
}
}
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h
index 5250b8d9b..6a3309a2c 100644
--- a/src/video_core/engines/kepler_compute.h
+++ b/src/video_core/engines/kepler_compute.h
@@ -140,7 +140,7 @@ public:
BitField<0, 16, u32> shared_alloc;
- BitField<0, 31, u32> block_dim_x;
+ BitField<16, 16, u32> block_dim_x;
union {
BitField<0, 16, u32> block_dim_y;
BitField<16, 16, u32> block_dim_z;
@@ -153,7 +153,7 @@ public:
INSERT_PADDING_WORDS(0x8);
- struct {
+ struct ConstBufferConfig {
u32 address_low;
union {
BitField<0, 8, u32> address_high;
@@ -163,7 +163,8 @@ public:
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high.Value()) << 32) |
address_low);
}
- } const_buffer_config[8];
+ };
+ std::array<ConstBufferConfig, NumConstBuffers> const_buffer_config;
union {
BitField<0, 20, u32> local_pos_alloc;
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index 113f9d8f3..43a84bd52 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -163,8 +163,8 @@ private:
static constexpr u64 page_size{1 << page_bits};
static constexpr u64 page_mask{page_size - 1};
- /// Address space in bits, this is fairly arbitrary but sufficiently large.
- static constexpr u32 address_space_width{39};
+ /// Address space in bits, according to Tegra X1 TRM
+ static constexpr u32 address_space_width{40};
/// Start address for mapping, this is fairly arbitrary but must be non-zero.
static constexpr GPUVAddr address_space_base{0x100000};
/// End of address space, based on address space in bits.
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 739477cc9..7dc2e0560 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -143,6 +143,24 @@ u32 GetGenericAttributeIndex(Attribute::Index index) {
return static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0);
}
+constexpr const char* GetFlowStackPrefix(MetaStackClass stack) {
+ switch (stack) {
+ case MetaStackClass::Ssy:
+ return "ssy";
+ case MetaStackClass::Pbk:
+ return "pbk";
+ }
+ return {};
+}
+
+std::string FlowStackName(MetaStackClass stack) {
+ return fmt::format("{}_flow_stack", GetFlowStackPrefix(stack));
+}
+
+std::string FlowStackTopName(MetaStackClass stack) {
+ return fmt::format("{}_flow_stack_top", GetFlowStackPrefix(stack));
+}
+
class GLSLDecompiler final {
public:
explicit GLSLDecompiler(const Device& device, const ShaderIR& ir, ShaderStage stage,
@@ -173,8 +191,10 @@ public:
// TODO(Subv): Figure out the actual depth of the flow stack, for now it seems
// unlikely that shaders will use 20 nested SSYs and PBKs.
constexpr u32 FLOW_STACK_SIZE = 20;
- code.AddLine("uint flow_stack[{}];", FLOW_STACK_SIZE);
- code.AddLine("uint flow_stack_top = 0u;");
+ for (const auto stack : std::array{MetaStackClass::Ssy, MetaStackClass::Pbk}) {
+ code.AddLine("uint {}[{}];", FlowStackName(stack), FLOW_STACK_SIZE);
+ code.AddLine("uint {} = 0u;", FlowStackTopName(stack));
+ }
code.AddLine("while (true) {{");
++code.scope;
@@ -1438,15 +1458,18 @@ private:
}
std::string PushFlowStack(Operation operation) {
+ const auto stack = std::get<MetaStackClass>(operation.GetMeta());
const auto target = std::get_if<ImmediateNode>(&*operation[0]);
UNIMPLEMENTED_IF(!target);
- code.AddLine("flow_stack[flow_stack_top++] = 0x{:x}u;", target->GetValue());
+ code.AddLine("{}[{}++] = 0x{:x}u;", FlowStackName(stack), FlowStackTopName(stack),
+ target->GetValue());
return {};
}
std::string PopFlowStack(Operation operation) {
- code.AddLine("jmp_to = flow_stack[--flow_stack_top];");
+ const auto stack = std::get<MetaStackClass>(operation.GetMeta());
+ code.AddLine("jmp_to = {}[--{}];", FlowStackName(stack), FlowStackTopName(stack));
code.AddLine("break;");
return {};
}
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 547883425..33ad9764a 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -132,20 +132,16 @@ public:
branch_labels.push_back(label);
}
- // TODO(Rodrigo): Figure out the actual depth of the flow stack, for now it seems unlikely
- // that shaders will use 20 nested SSYs and PBKs.
- constexpr u32 FLOW_STACK_SIZE = 20;
- const Id flow_stack_type = TypeArray(t_uint, Constant(t_uint, FLOW_STACK_SIZE));
jmp_to = Emit(OpVariable(TypePointer(spv::StorageClass::Function, t_uint),
spv::StorageClass::Function, Constant(t_uint, first_address)));
- flow_stack = Emit(OpVariable(TypePointer(spv::StorageClass::Function, flow_stack_type),
- spv::StorageClass::Function, ConstantNull(flow_stack_type)));
- flow_stack_top =
- Emit(OpVariable(t_func_uint, spv::StorageClass::Function, Constant(t_uint, 0)));
+ std::tie(ssy_flow_stack, ssy_flow_stack_top) = CreateFlowStack();
+ std::tie(pbk_flow_stack, pbk_flow_stack_top) = CreateFlowStack();
Name(jmp_to, "jmp_to");
- Name(flow_stack, "flow_stack");
- Name(flow_stack_top, "flow_stack_top");
+ Name(ssy_flow_stack, "ssy_flow_stack");
+ Name(ssy_flow_stack_top, "ssy_flow_stack_top");
+ Name(pbk_flow_stack, "pbk_flow_stack");
+ Name(pbk_flow_stack_top, "pbk_flow_stack_top");
Emit(OpBranch(loop_label));
Emit(loop_label);
@@ -952,6 +948,7 @@ private:
const auto target = std::get_if<ImmediateNode>(&*operation[0]);
ASSERT(target);
+ const auto [flow_stack, flow_stack_top] = GetFlowStack(operation);
const Id current = Emit(OpLoad(t_uint, flow_stack_top));
const Id next = Emit(OpIAdd(t_uint, current, Constant(t_uint, 1)));
const Id access = Emit(OpAccessChain(t_func_uint, flow_stack, current));
@@ -962,6 +959,7 @@ private:
}
Id PopFlowStack(Operation operation) {
+ const auto [flow_stack, flow_stack_top] = GetFlowStack(operation);
const Id current = Emit(OpLoad(t_uint, flow_stack_top));
const Id previous = Emit(OpISub(t_uint, current, Constant(t_uint, 1)));
const Id access = Emit(OpAccessChain(t_func_uint, flow_stack, previous));
@@ -1172,6 +1170,31 @@ private:
Emit(skip_label);
}
+ std::tuple<Id, Id> CreateFlowStack() {
+ // TODO(Rodrigo): Figure out the actual depth of the flow stack, for now it seems unlikely
+ // that shaders will use 20 nested SSYs and PBKs.
+ constexpr u32 FLOW_STACK_SIZE = 20;
+ constexpr auto storage_class = spv::StorageClass::Function;
+
+ const Id flow_stack_type = TypeArray(t_uint, Constant(t_uint, FLOW_STACK_SIZE));
+ const Id stack = Emit(OpVariable(TypePointer(storage_class, flow_stack_type), storage_class,
+ ConstantNull(flow_stack_type)));
+ const Id top = Emit(OpVariable(t_func_uint, storage_class, Constant(t_uint, 0)));
+ return std::tie(stack, top);
+ }
+
+ std::pair<Id, Id> GetFlowStack(Operation operation) {
+ const auto stack_class = std::get<MetaStackClass>(operation.GetMeta());
+ switch (stack_class) {
+ case MetaStackClass::Ssy:
+ return {ssy_flow_stack, ssy_flow_stack_top};
+ case MetaStackClass::Pbk:
+ return {pbk_flow_stack, pbk_flow_stack_top};
+ }
+ UNREACHABLE();
+ return {};
+ }
+
static constexpr OperationDecompilersArray operation_decompilers = {
&SPIRVDecompiler::Assign,
@@ -1414,8 +1437,10 @@ private:
Id execute_function{};
Id jmp_to{};
- Id flow_stack_top{};
- Id flow_stack{};
+ Id ssy_flow_stack_top{};
+ Id pbk_flow_stack_top{};
+ Id ssy_flow_stack{};
+ Id pbk_flow_stack{};
Id continue_label{};
std::map<u32, Id> labels;
};
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp
index 6fc07f213..d46a8ab82 100644
--- a/src/video_core/shader/decode/other.cpp
+++ b/src/video_core/shader/decode/other.cpp
@@ -109,22 +109,20 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0,
"Constant buffer flow is not supported");
- // The SSY opcode tells the GPU where to re-converge divergent execution paths, it sets the
- // target of the jump that the SYNC instruction will make. The SSY opcode has a similar
- // structure to the BRA opcode.
+ // The SSY opcode tells the GPU where to re-converge divergent execution paths with SYNC.
const u32 target = pc + instr.bra.GetBranchTarget();
- bb.push_back(Operation(OperationCode::PushFlowStack, Immediate(target)));
+ bb.push_back(
+ Operation(OperationCode::PushFlowStack, MetaStackClass::Ssy, Immediate(target)));
break;
}
case OpCode::Id::PBK: {
UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0,
"Constant buffer PBK is not supported");
- // PBK pushes to a stack the address where BRK will jump to. This shares stack with SSY but
- // using SYNC on a PBK address will kill the shader execution. We don't emulate this because
- // it's very unlikely a driver will emit such invalid shader.
+ // PBK pushes to a stack the address where BRK will jump to.
const u32 target = pc + instr.bra.GetBranchTarget();
- bb.push_back(Operation(OperationCode::PushFlowStack, Immediate(target)));
+ bb.push_back(
+ Operation(OperationCode::PushFlowStack, MetaStackClass::Pbk, Immediate(target)));
break;
}
case OpCode::Id::SYNC: {
@@ -133,7 +131,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
static_cast<u32>(cc));
// The SYNC opcode jumps to the address previously set by the SSY opcode
- bb.push_back(Operation(OperationCode::PopFlowStack));
+ bb.push_back(Operation(OperationCode::PopFlowStack, MetaStackClass::Ssy));
break;
}
case OpCode::Id::BRK: {
@@ -142,7 +140,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
static_cast<u32>(cc));
// The BRK opcode jumps to the address previously set by the PBK opcode
- bb.push_back(Operation(OperationCode::PopFlowStack));
+ bb.push_back(Operation(OperationCode::PopFlowStack, MetaStackClass::Pbk));
break;
}
case OpCode::Id::IPA: {
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index c002f90f9..3cfb911bb 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -174,6 +174,11 @@ enum class InternalFlag {
Amount = 4,
};
+enum class MetaStackClass {
+ Ssy,
+ Pbk,
+};
+
class OperationNode;
class ConditionalNode;
class GprNode;
@@ -285,7 +290,7 @@ struct MetaTexture {
};
/// Parameters that modify an operation but are not part of any particular operand
-using Meta = std::variant<MetaArithmetic, MetaTexture, Tegra::Shader::HalfType>;
+using Meta = std::variant<MetaArithmetic, MetaTexture, MetaStackClass, Tegra::Shader::HalfType>;
/// Holds any kind of operation that can be done in the IR
class OperationNode final {
diff --git a/src/yuzu/applets/profile_select.cpp b/src/yuzu/applets/profile_select.cpp
index 6b5c7ba61..6aff38735 100644
--- a/src/yuzu/applets/profile_select.cpp
+++ b/src/yuzu/applets/profile_select.cpp
@@ -12,21 +12,11 @@
#include <QVBoxLayout>
#include "common/file_util.h"
#include "common/string_util.h"
+#include "core/constants.h"
#include "core/hle/lock.h"
#include "yuzu/applets/profile_select.h"
#include "yuzu/main.h"
-// Same backup JPEG used by acc IProfile::GetImage if no jpeg found
-constexpr std::array<u8, 107> backup_jpeg{
- 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
- 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x06, 0x06, 0x05,
- 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a, 0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e,
- 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13,
- 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10, 0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01,
- 0x01, 0x01, 0x11, 0x00, 0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08,
- 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,
-};
-
QString FormatUserEntryText(const QString& username, Common::UUID uuid) {
return QtProfileSelectionDialog::tr(
"%1\n%2", "%1 is the profile username, %2 is the formatted UUID (e.g. "
@@ -45,7 +35,8 @@ QPixmap GetIcon(Common::UUID uuid) {
if (!icon) {
icon.fill(Qt::black);
- icon.loadFromData(backup_jpeg.data(), static_cast<u32>(backup_jpeg.size()));
+ icon.loadFromData(Core::Constants::ACCOUNT_BACKUP_JPEG.data(),
+ static_cast<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size()));
}
return icon.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index 110842eb2..f370c690f 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -4,6 +4,8 @@
#include <memory>
+#include <QSignalBlocker>
+
#include "audio_core/sink.h"
#include "audio_core/sink_details.h"
#include "core/core.h"
@@ -15,19 +17,15 @@ ConfigureAudio::ConfigureAudio(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()) {
ui->setupUi(this);
- ui->output_sink_combo_box->clear();
- ui->output_sink_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name));
- for (const char* id : AudioCore::GetSinkIDs()) {
- ui->output_sink_combo_box->addItem(QString::fromUtf8(id));
- }
+ InitializeAudioOutputSinkComboBox();
connect(ui->volume_slider, &QSlider::valueChanged, this,
&ConfigureAudio::SetVolumeIndicatorText);
-
- SetConfiguration();
connect(ui->output_sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this,
&ConfigureAudio::UpdateAudioDevices);
+ SetConfiguration();
+
const bool is_powered_on = Core::System::GetInstance().IsPoweredOn();
ui->output_sink_combo_box->setEnabled(!is_powered_on);
ui->audio_device_combo_box->setEnabled(!is_powered_on);
@@ -49,8 +47,9 @@ void ConfigureAudio::SetConfiguration() {
}
void ConfigureAudio::SetOutputSinkFromSinkID() {
- int new_sink_index = 0;
+ [[maybe_unused]] const QSignalBlocker blocker(ui->output_sink_combo_box);
+ int new_sink_index = 0;
const QString sink_id = QString::fromStdString(Settings::values.sink_id);
for (int index = 0; index < ui->output_sink_combo_box->count(); index++) {
if (ui->output_sink_combo_box->itemText(index) == sink_id) {
@@ -92,6 +91,14 @@ void ConfigureAudio::ApplyConfiguration() {
static_cast<float>(ui->volume_slider->sliderPosition()) / ui->volume_slider->maximum();
}
+void ConfigureAudio::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QWidget::changeEvent(event);
+}
+
void ConfigureAudio::UpdateAudioDevices(int sink_index) {
ui->audio_device_combo_box->clear();
ui->audio_device_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name));
@@ -102,6 +109,16 @@ void ConfigureAudio::UpdateAudioDevices(int sink_index) {
}
}
+void ConfigureAudio::InitializeAudioOutputSinkComboBox() {
+ ui->output_sink_combo_box->clear();
+ ui->output_sink_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name));
+
+ for (const char* id : AudioCore::GetSinkIDs()) {
+ ui->output_sink_combo_box->addItem(QString::fromUtf8(id));
+ }
+}
+
void ConfigureAudio::RetranslateUI() {
ui->retranslateUi(this);
+ SetVolumeIndicatorText(ui->volume_slider->sliderPosition());
}
diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h
index 2bb92d9b5..ea83bd72d 100644
--- a/src/yuzu/configuration/configure_audio.h
+++ b/src/yuzu/configuration/configure_audio.h
@@ -19,9 +19,14 @@ public:
~ConfigureAudio() override;
void ApplyConfiguration();
- void RetranslateUI();
private:
+ void changeEvent(QEvent* event) override;
+
+ void InitializeAudioOutputSinkComboBox();
+
+ void RetranslateUI();
+
void UpdateAudioDevices(int sink_index);
void SetConfiguration();
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index afc2e3b38..efc2bedfd 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -51,3 +51,15 @@ void ConfigureDebug::ApplyConfiguration() {
filter.ParseFilterString(Settings::values.log_filter);
Log::SetGlobalFilter(filter);
}
+
+void ConfigureDebug::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QWidget::changeEvent(event);
+}
+
+void ConfigureDebug::RetranslateUI() {
+ ui->retranslateUi(this);
+}
diff --git a/src/yuzu/configuration/configure_debug.h b/src/yuzu/configuration/configure_debug.h
index 06b89026c..f4805a1d8 100644
--- a/src/yuzu/configuration/configure_debug.h
+++ b/src/yuzu/configuration/configure_debug.h
@@ -21,6 +21,9 @@ public:
void ApplyConfiguration();
private:
+ void changeEvent(QEvent* event) override;
+
+ void RetranslateUI();
void SetConfiguration();
std::unique_ptr<Ui::ConfigureDebug> ui;
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index a1b1e00bc..e636964e3 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -4,6 +4,7 @@
#include <QHash>
#include <QListWidgetItem>
+#include <QSignalBlocker>
#include "core/settings.h"
#include "ui_configure.h"
#include "yuzu/configuration/config.h"
@@ -46,13 +47,38 @@ void ConfigureDialog::ApplyConfiguration() {
Settings::LogSettings();
}
+void ConfigureDialog::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QDialog::changeEvent(event);
+}
+
+void ConfigureDialog::RetranslateUI() {
+ const int old_row = ui->selectorList->currentRow();
+ const int old_index = ui->tabWidget->currentIndex();
+
+ ui->retranslateUi(this);
+
+ PopulateSelectionList();
+ ui->selectorList->setCurrentRow(old_row);
+
+ UpdateVisibleTabs();
+ ui->tabWidget->setCurrentIndex(old_index);
+}
+
void ConfigureDialog::PopulateSelectionList() {
const std::array<std::pair<QString, QStringList>, 4> items{
{{tr("General"), {tr("General"), tr("Web"), tr("Debug"), tr("Game List")}},
{tr("System"), {tr("System"), tr("Profiles"), tr("Audio")}},
{tr("Graphics"), {tr("Graphics")}},
- {tr("Controls"), {tr("Input"), tr("Hotkeys")}}}};
+ {tr("Controls"), {tr("Input"), tr("Hotkeys")}}},
+ };
+ [[maybe_unused]] const QSignalBlocker blocker(ui->selectorList);
+
+ ui->selectorList->clear();
for (const auto& entry : items) {
auto* const item = new QListWidgetItem(entry.first);
item->setData(Qt::UserRole, entry.second);
@@ -63,24 +89,28 @@ void ConfigureDialog::PopulateSelectionList() {
void ConfigureDialog::UpdateVisibleTabs() {
const auto items = ui->selectorList->selectedItems();
- if (items.isEmpty())
+ if (items.isEmpty()) {
return;
+ }
- const std::map<QString, QWidget*> widgets = {{tr("General"), ui->generalTab},
- {tr("System"), ui->systemTab},
- {tr("Profiles"), ui->profileManagerTab},
- {tr("Input"), ui->inputTab},
- {tr("Hotkeys"), ui->hotkeysTab},
- {tr("Graphics"), ui->graphicsTab},
- {tr("Audio"), ui->audioTab},
- {tr("Debug"), ui->debugTab},
- {tr("Web"), ui->webTab},
- {tr("Game List"), ui->gameListTab}};
+ const std::map<QString, QWidget*> widgets = {
+ {tr("General"), ui->generalTab},
+ {tr("System"), ui->systemTab},
+ {tr("Profiles"), ui->profileManagerTab},
+ {tr("Input"), ui->inputTab},
+ {tr("Hotkeys"), ui->hotkeysTab},
+ {tr("Graphics"), ui->graphicsTab},
+ {tr("Audio"), ui->audioTab},
+ {tr("Debug"), ui->debugTab},
+ {tr("Web"), ui->webTab},
+ {tr("Game List"), ui->gameListTab},
+ };
+
+ [[maybe_unused]] const QSignalBlocker blocker(ui->tabWidget);
ui->tabWidget->clear();
-
const QStringList tabs = items[0]->data(Qt::UserRole).toStringList();
-
- for (const auto& tab : tabs)
+ for (const auto& tab : tabs) {
ui->tabWidget->addTab(widgets.find(tab)->second, tab);
+ }
}
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index 7e7d90f59..2d3bfc2da 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -23,6 +23,10 @@ public:
void ApplyConfiguration();
private:
+ void changeEvent(QEvent* event) override;
+
+ void RetranslateUI();
+
void SetConfiguration();
void UpdateVisibleTabs();
void PopulateSelectionList();
diff --git a/src/yuzu/configuration/configure_gamelist.cpp b/src/yuzu/configuration/configure_gamelist.cpp
index 4b5b0ee48..d1724ba89 100644
--- a/src/yuzu/configuration/configure_gamelist.cpp
+++ b/src/yuzu/configuration/configure_gamelist.cpp
@@ -77,7 +77,6 @@ void ConfigureGameList::SetConfiguration() {
void ConfigureGameList::changeEvent(QEvent* event) {
if (event->type() == QEvent::LanguageChange) {
RetranslateUI();
- return;
}
QWidget::changeEvent(event);
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 8bdc1787a..06d368dfc 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -45,3 +45,15 @@ void ConfigureGeneral::ApplyConfiguration() {
Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked();
}
+
+void ConfigureGeneral::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QWidget::changeEvent(event);
+}
+
+void ConfigureGeneral::RetranslateUI() {
+ ui->retranslateUi(this);
+}
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h
index fd5fd2a91..ef05ce065 100644
--- a/src/yuzu/configuration/configure_general.h
+++ b/src/yuzu/configuration/configure_general.h
@@ -23,6 +23,9 @@ public:
void ApplyConfiguration();
private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+
void SetConfiguration();
std::unique_ptr<Ui::ConfigureGeneral> ui;
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 902ef5cd4..2b17b250c 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -101,6 +101,18 @@ void ConfigureGraphics::ApplyConfiguration() {
Settings::values.bg_blue = static_cast<float>(bg_color.blueF());
}
+void ConfigureGraphics::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QWidget::changeEvent(event);
+}
+
+void ConfigureGraphics::RetranslateUI() {
+ ui->retranslateUi(this);
+}
+
void ConfigureGraphics::UpdateBackgroundColorButton(QColor color) {
bg_color = color;
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h
index 6b3c39705..fae28d98e 100644
--- a/src/yuzu/configuration/configure_graphics.h
+++ b/src/yuzu/configuration/configure_graphics.h
@@ -21,6 +21,9 @@ public:
void ApplyConfiguration();
private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+
void SetConfiguration();
void UpdateBackgroundColorButton(QColor color);
diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp
index 04119e9d7..3ea0b8d67 100644
--- a/src/yuzu/configuration/configure_hotkeys.cpp
+++ b/src/yuzu/configuration/configure_hotkeys.cpp
@@ -17,7 +17,6 @@ ConfigureHotkeys::ConfigureHotkeys(QWidget* parent)
model = new QStandardItemModel(this);
model->setColumnCount(3);
- model->setHorizontalHeaderLabels({tr("Action"), tr("Hotkey"), tr("Context")});
connect(ui->hotkey_list, &QTreeView::doubleClicked, this, &ConfigureHotkeys::Configure);
ui->hotkey_list->setModel(model);
@@ -27,6 +26,8 @@ ConfigureHotkeys::ConfigureHotkeys(QWidget* parent)
ui->hotkey_list->setColumnWidth(0, 200);
ui->hotkey_list->resizeColumnToContents(1);
+
+ RetranslateUI();
}
ConfigureHotkeys::~ConfigureHotkeys() = default;
@@ -49,6 +50,20 @@ void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) {
ui->hotkey_list->expandAll();
}
+void ConfigureHotkeys::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QWidget::changeEvent(event);
+}
+
+void ConfigureHotkeys::RetranslateUI() {
+ ui->retranslateUi(this);
+
+ model->setHorizontalHeaderLabels({tr("Action"), tr("Hotkey"), tr("Context")});
+}
+
void ConfigureHotkeys::Configure(QModelIndex index) {
if (!index.parent().isValid()) {
return;
@@ -112,7 +127,3 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) {
registry.SaveHotkeys();
}
-
-void ConfigureHotkeys::RetranslateUI() {
- ui->retranslateUi(this);
-}
diff --git a/src/yuzu/configuration/configure_hotkeys.h b/src/yuzu/configuration/configure_hotkeys.h
index a1f4c7134..8f8c6173b 100644
--- a/src/yuzu/configuration/configure_hotkeys.h
+++ b/src/yuzu/configuration/configure_hotkeys.h
@@ -22,7 +22,6 @@ public:
~ConfigureHotkeys() override;
void ApplyConfiguration(HotkeyRegistry& registry);
- void RetranslateUI();
/**
* Populates the hotkey list widget using data from the provided registry.
@@ -32,6 +31,9 @@ public:
void Populate(const HotkeyRegistry& registry);
private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+
void Configure(QModelIndex index);
bool IsUsedKey(QKeySequence key_sequence) const;
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index fb1210bcb..4dd775aab 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -5,6 +5,7 @@
#include <algorithm>
#include <memory>
+#include <QSignalBlocker>
#include <QTimer>
#include "configuration/configure_touchscreen_advanced.h"
@@ -74,11 +75,7 @@ ConfigureInput::ConfigureInput(QWidget* parent)
ui->player5_configure, ui->player6_configure, ui->player7_configure, ui->player8_configure,
};
- for (auto* controller_box : players_controller) {
- controller_box->addItems({tr("None"), tr("Pro Controller"), tr("Dual Joycons"),
- tr("Single Right Joycon"), tr("Single Left Joycon")});
- }
-
+ RetranslateUI();
LoadConfiguration();
UpdateUIEnabled();
@@ -144,6 +141,31 @@ void ConfigureInput::ApplyConfiguration() {
Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked();
}
+void ConfigureInput::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QDialog::changeEvent(event);
+}
+
+void ConfigureInput::RetranslateUI() {
+ ui->retranslateUi(this);
+ RetranslateControllerComboBoxes();
+}
+
+void ConfigureInput::RetranslateControllerComboBoxes() {
+ for (auto* controller_box : players_controller) {
+ [[maybe_unused]] const QSignalBlocker blocker(controller_box);
+
+ controller_box->clear();
+ controller_box->addItems({tr("None"), tr("Pro Controller"), tr("Dual Joycons"),
+ tr("Single Right Joycon"), tr("Single Left Joycon")});
+ }
+
+ LoadPlayerControllerIndices();
+}
+
void ConfigureInput::UpdateUIEnabled() {
bool hit_disabled = false;
for (auto* player : players_controller) {
@@ -175,11 +197,7 @@ void ConfigureInput::LoadConfiguration() {
Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD),
[](const auto& player) { return player.connected; });
- for (std::size_t i = 0; i < players_controller.size(); ++i) {
- const auto connected = Settings::values.players[i].connected;
- players_controller[i]->setCurrentIndex(
- connected ? static_cast<u8>(Settings::values.players[i].type) + 1 : 0);
- }
+ LoadPlayerControllerIndices();
ui->use_docked_mode->setChecked(Settings::values.use_docked_mode);
ui->handheld_connected->setChecked(
@@ -194,6 +212,14 @@ void ConfigureInput::LoadConfiguration() {
UpdateUIEnabled();
}
+void ConfigureInput::LoadPlayerControllerIndices() {
+ for (std::size_t i = 0; i < players_controller.size(); ++i) {
+ const auto connected = Settings::values.players[i].connected;
+ players_controller[i]->setCurrentIndex(
+ connected ? static_cast<u8>(Settings::values.players[i].type) + 1 : 0);
+ }
+}
+
void ConfigureInput::RestoreDefaults() {
players_controller[0]->setCurrentIndex(2);
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h
index 6a2125215..2f70cb3ca 100644
--- a/src/yuzu/configuration/configure_input.h
+++ b/src/yuzu/configuration/configure_input.h
@@ -33,10 +33,16 @@ public:
void ApplyConfiguration();
private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+ void RetranslateControllerComboBoxes();
+
void UpdateUIEnabled();
/// Load configuration settings.
void LoadConfiguration();
+ void LoadPlayerControllerIndices();
+
/// Restore all buttons to their default values.
void RestoreDefaults();
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 32d2a6815..916baccc1 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -373,6 +373,19 @@ void ConfigureInputPlayer::ApplyConfiguration() {
Settings::values.players[player_index].button_color_right = colors[3];
}
+void ConfigureInputPlayer::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QDialog::changeEvent(event);
+}
+
+void ConfigureInputPlayer::RetranslateUI() {
+ ui->retranslateUi(this);
+ UpdateButtonLabels();
+}
+
void ConfigureInputPlayer::OnControllerButtonClick(int i) {
const QColor new_bg_color = QColorDialog::getColor(controller_colors[i]);
if (!new_bg_color.isValid())
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index 27924fcce..c66027651 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -41,6 +41,9 @@ public:
void ApplyConfiguration();
private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+
void OnControllerButtonClick(int i);
/// Load configuration settings.
diff --git a/src/yuzu/configuration/configure_input_simple.cpp b/src/yuzu/configuration/configure_input_simple.cpp
index 6140a5573..864803ea3 100644
--- a/src/yuzu/configuration/configure_input_simple.cpp
+++ b/src/yuzu/configuration/configure_input_simple.cpp
@@ -119,6 +119,18 @@ void ConfigureInputSimple::ApplyConfiguration() {
UISettings::values.profile_index = index;
}
+void ConfigureInputSimple::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QWidget::changeEvent(event);
+}
+
+void ConfigureInputSimple::RetranslateUI() {
+ ui->retranslateUi(this);
+}
+
void ConfigureInputSimple::LoadConfiguration() {
const auto index = UISettings::values.profile_index;
if (index >= static_cast<int>(INPUT_PROFILES.size()) || index < 0) {
diff --git a/src/yuzu/configuration/configure_input_simple.h b/src/yuzu/configuration/configure_input_simple.h
index 573c2db2b..bb5050224 100644
--- a/src/yuzu/configuration/configure_input_simple.h
+++ b/src/yuzu/configuration/configure_input_simple.h
@@ -30,6 +30,9 @@ public:
void ApplyConfiguration();
private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+
/// Load configuration settings.
void LoadConfiguration();
diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp
index 26f53128f..b7305e653 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.cpp
+++ b/src/yuzu/configuration/configure_mouse_advanced.cpp
@@ -140,6 +140,18 @@ void ConfigureMouseAdvanced::LoadConfiguration() {
UpdateButtonLabels();
}
+void ConfigureMouseAdvanced::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QDialog::changeEvent(event);
+}
+
+void ConfigureMouseAdvanced::RetranslateUI() {
+ ui->retranslateUi(this);
+}
+
void ConfigureMouseAdvanced::RestoreDefaults() {
for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) {
buttons_param[button_id] = Common::ParamPackage{
diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h
index 373f992c9..342b82412 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.h
+++ b/src/yuzu/configuration/configure_mouse_advanced.h
@@ -28,6 +28,9 @@ public:
void ApplyConfiguration();
private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+
/// Load configuration settings.
void LoadConfiguration();
/// Restore all buttons to their default values.
diff --git a/src/yuzu/configuration/configure_per_general.cpp b/src/yuzu/configuration/configure_per_general.cpp
index 275519c7b..90336e235 100644
--- a/src/yuzu/configuration/configure_per_general.cpp
+++ b/src/yuzu/configuration/configure_per_general.cpp
@@ -92,6 +92,18 @@ void ConfigurePerGameGeneral::ApplyConfiguration() {
Settings::values.disabled_addons[title_id] = disabled_addons;
}
+void ConfigurePerGameGeneral::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QDialog::changeEvent(event);
+}
+
+void ConfigurePerGameGeneral::RetranslateUI() {
+ ui->retranslateUi(this);
+}
+
void ConfigurePerGameGeneral::LoadFromFile(FileSys::VirtualFile file) {
this->file = std::move(file);
LoadConfiguration();
diff --git a/src/yuzu/configuration/configure_per_general.h b/src/yuzu/configuration/configure_per_general.h
index b95e07079..a3b2cdeff 100644
--- a/src/yuzu/configuration/configure_per_general.h
+++ b/src/yuzu/configuration/configure_per_general.h
@@ -35,6 +35,9 @@ public:
void LoadFromFile(FileSys::VirtualFile file);
private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+
void LoadConfiguration();
std::unique_ptr<Ui::ConfigurePerGameGeneral> ui;
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index 7c1597488..c90f4cdd8 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -80,11 +80,10 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent)
profile_manager(std::make_unique<Service::Account::ProfileManager>()) {
ui->setupUi(this);
- layout = new QVBoxLayout;
tree_view = new QTreeView;
item_model = new QStandardItemModel(tree_view);
+ item_model->insertColumns(0, 1);
tree_view->setModel(item_model);
-
tree_view->setAlternatingRowColors(true);
tree_view->setSelectionMode(QHeaderView::SingleSelection);
tree_view->setSelectionBehavior(QHeaderView::SelectRows);
@@ -96,13 +95,11 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent)
tree_view->setIconSize({64, 64});
tree_view->setContextMenuPolicy(Qt::NoContextMenu);
- item_model->insertColumns(0, 1);
- item_model->setHeaderData(0, Qt::Horizontal, tr("Users"));
-
// We must register all custom types with the Qt Automoc system so that we are able to use it
// with signals/slots. In this case, QList falls under the umbrells of custom types.
qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>");
+ layout = new QVBoxLayout;
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
layout->addWidget(tree_view);
@@ -120,10 +117,24 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent)
ui->current_user_icon->setScene(scene);
SetConfiguration();
+ RetranslateUI();
}
ConfigureProfileManager::~ConfigureProfileManager() = default;
+void ConfigureProfileManager::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QWidget::changeEvent(event);
+}
+
+void ConfigureProfileManager::RetranslateUI() {
+ ui->retranslateUi(this);
+ item_model->setHeaderData(0, Qt::Horizontal, tr("Users"));
+}
+
void ConfigureProfileManager::SetConfiguration() {
enabled = !Core::System::GetInstance().IsPoweredOn();
item_model->removeRows(0, item_model->rowCount());
diff --git a/src/yuzu/configuration/configure_profile_manager.h b/src/yuzu/configuration/configure_profile_manager.h
index 4e9b4e8ea..0a9bca2a6 100644
--- a/src/yuzu/configuration/configure_profile_manager.h
+++ b/src/yuzu/configuration/configure_profile_manager.h
@@ -33,6 +33,9 @@ public:
void ApplyConfiguration();
private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+
void SetConfiguration();
void PopulateUserList();
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 5f0ed2f61..e1b52f8d9 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -40,6 +40,18 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::
ConfigureSystem::~ConfigureSystem() = default;
+void ConfigureSystem::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QWidget::changeEvent(event);
+}
+
+void ConfigureSystem::RetranslateUI() {
+ ui->retranslateUi(this);
+}
+
void ConfigureSystem::SetConfiguration() {
enabled = !Core::System::GetInstance().IsPoweredOn();
diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h
index 4c0329d57..1eab3781d 100644
--- a/src/yuzu/configuration/configure_system.h
+++ b/src/yuzu/configuration/configure_system.h
@@ -23,6 +23,9 @@ public:
void ApplyConfiguration();
private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+
void SetConfiguration();
void ReadSystemSettings();
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.cpp b/src/yuzu/configuration/configure_touchscreen_advanced.cpp
index bad224239..8ced28c75 100644
--- a/src/yuzu/configuration/configure_touchscreen_advanced.cpp
+++ b/src/yuzu/configuration/configure_touchscreen_advanced.cpp
@@ -20,6 +20,18 @@ ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent)
ConfigureTouchscreenAdvanced::~ConfigureTouchscreenAdvanced() = default;
+void ConfigureTouchscreenAdvanced::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QDialog::changeEvent(event);
+}
+
+void ConfigureTouchscreenAdvanced::RetranslateUI() {
+ ui->retranslateUi(this);
+}
+
void ConfigureTouchscreenAdvanced::ApplyConfiguration() {
Settings::values.touchscreen.finger = ui->finger_box->value();
Settings::values.touchscreen.diameter_x = ui->diameter_x_box->value();
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.h b/src/yuzu/configuration/configure_touchscreen_advanced.h
index 94edd85b1..72061492c 100644
--- a/src/yuzu/configuration/configure_touchscreen_advanced.h
+++ b/src/yuzu/configuration/configure_touchscreen_advanced.h
@@ -21,6 +21,9 @@ public:
void ApplyConfiguration();
private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+
/// Load configuration settings.
void LoadConfiguration();
/// Restore all buttons to their default values.
diff --git a/src/yuzu/configuration/configure_web.cpp b/src/yuzu/configuration/configure_web.cpp
index 8cacb75f3..5a70ef168 100644
--- a/src/yuzu/configuration/configure_web.cpp
+++ b/src/yuzu/configuration/configure_web.cpp
@@ -22,35 +22,55 @@ ConfigureWeb::ConfigureWeb(QWidget* parent)
#ifndef USE_DISCORD_PRESENCE
ui->discord_group->setVisible(false);
#endif
+
SetConfiguration();
+ RetranslateUI();
}
ConfigureWeb::~ConfigureWeb() = default;
-void ConfigureWeb::SetConfiguration() {
- ui->web_credentials_disclaimer->setWordWrap(true);
- ui->telemetry_learn_more->setOpenExternalLinks(true);
+void ConfigureWeb::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QWidget::changeEvent(event);
+}
+
+void ConfigureWeb::RetranslateUI() {
+ ui->retranslateUi(this);
+
ui->telemetry_learn_more->setText(
tr("<a href='https://yuzu-emu.org/help/feature/telemetry/'><span style=\"text-decoration: "
"underline; color:#039be5;\">Learn more</span></a>"));
- ui->web_signup_link->setOpenExternalLinks(true);
ui->web_signup_link->setText(
tr("<a href='https://profile.yuzu-emu.org/'><span style=\"text-decoration: underline; "
"color:#039be5;\">Sign up</span></a>"));
- ui->web_token_info_link->setOpenExternalLinks(true);
+
ui->web_token_info_link->setText(
tr("<a href='https://yuzu-emu.org/wiki/yuzu-web-service/'><span style=\"text-decoration: "
"underline; color:#039be5;\">What is my token?</span></a>"));
+ ui->label_telemetry_id->setText(
+ tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper()));
+}
+
+void ConfigureWeb::SetConfiguration() {
+ ui->web_credentials_disclaimer->setWordWrap(true);
+
+ ui->telemetry_learn_more->setOpenExternalLinks(true);
+ ui->web_signup_link->setOpenExternalLinks(true);
+ ui->web_token_info_link->setOpenExternalLinks(true);
+
ui->toggle_telemetry->setChecked(Settings::values.enable_telemetry);
ui->edit_username->setText(QString::fromStdString(Settings::values.yuzu_username));
ui->edit_token->setText(QString::fromStdString(Settings::values.yuzu_token));
+
// Connect after setting the values, to avoid calling OnLoginChanged now
connect(ui->edit_token, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged);
connect(ui->edit_username, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged);
- ui->label_telemetry_id->setText(
- tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper()));
+
user_verified = true;
ui->toggle_discordrpc->setChecked(UISettings::values.enable_discord_presence);
@@ -120,7 +140,3 @@ void ConfigureWeb::OnLoginVerified() {
"correctly, and that your internet connection is working."));
}
}
-
-void ConfigureWeb::RetranslateUI() {
- ui->retranslateUi(this);
-}
diff --git a/src/yuzu/configuration/configure_web.h b/src/yuzu/configuration/configure_web.h
index 49bee171b..9054711ea 100644
--- a/src/yuzu/configuration/configure_web.h
+++ b/src/yuzu/configuration/configure_web.h
@@ -20,9 +20,11 @@ public:
~ConfigureWeb() override;
void ApplyConfiguration();
- void RetranslateUI();
private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+
void RefreshTelemetryID();
void OnLoginChanged();
void VerifyLogin();